Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
beda529298 | ||
|
|
292bf42cb0 | ||
|
|
a8d1e69783 | ||
|
|
ab53f06bc6 | ||
|
|
053a154d1d | ||
|
|
7d08bac099 | ||
|
|
8e274700f4 | ||
|
|
22ae365ae9 | ||
|
|
ccd22e5a5a | ||
|
|
2692162617 | ||
|
|
d112b343e1 | ||
|
|
7ac8798d26 | ||
|
|
a41ce8e4a0 | ||
|
|
07fd1a3203 | ||
|
|
81ce8116b5 | ||
|
|
c82330b0bc | ||
|
|
50a518eac4 | ||
|
|
42d1610d52 | ||
|
|
ac51d22884 | ||
|
|
c42cca1c86 | ||
|
|
b51434b5a8 | ||
|
|
7dee79a96b | ||
|
|
ce93a03098 | ||
|
|
319aee73f2 | ||
|
|
5210ad3610 | ||
|
|
def8f9a2e3 | ||
|
|
f716f87a04 | ||
|
|
0375e92110 | ||
|
|
560c1adeb7 | ||
|
|
3c9875db19 | ||
|
|
89e2ac7ebf | ||
|
|
05ab66cf97 | ||
|
|
104dcf1d37 | ||
|
|
f2ef7a6169 | ||
|
|
58048b4bb1 | ||
|
|
332674a382 | ||
|
|
88ef908bad | ||
|
|
eb8c926eba | ||
|
|
73cba728a1 | ||
|
|
1446529f7c | ||
|
|
51649fd806 | ||
|
|
f55b663ea7 | ||
|
|
2360c406bf | ||
|
|
5db3763b2d | ||
|
|
bb0cad404b | ||
|
|
a6164f765c | ||
|
|
892c7b4d9c | ||
|
|
3fcb902fd9 | ||
|
|
8c9345fa1f | ||
|
|
5eab3620c9 | ||
|
|
80974e5b39 | ||
|
|
4f705b7cc9 | ||
|
|
e0eb375449 | ||
|
|
bbecbe43ec | ||
|
|
46865a5f40 | ||
|
|
b577c5f00f | ||
|
|
ee2a90880a | ||
|
|
31d89377da | ||
|
|
0c33a58579 | ||
|
|
3842cfd853 | ||
|
|
2e0dc40e3f | ||
|
|
c6f1382813 | ||
|
|
1220fbbd4b | ||
|
|
179148b0e5 | ||
|
|
4536b23a1d | ||
|
|
4571262803 | ||
|
|
27517cd8a0 | ||
|
|
54dd72de66 | ||
|
|
7978247fa7 | ||
|
|
7cadc6374a | ||
|
|
e194dad0da | ||
|
|
5f416b194a | ||
|
|
2a244616ad | ||
|
|
bfa3eebb7f | ||
|
|
b0c2fd8af2 | ||
|
|
cf90846161 | ||
|
|
89bb2d352d | ||
|
|
c1572e4ff4 | ||
|
|
1741d7ce1f | ||
|
|
05385b1cb0 | ||
|
|
3ba7aa3532 | ||
|
|
bb2a5f8d17 | ||
|
|
44d0dcba12 | ||
|
|
4c86af69a5 | ||
|
|
93663d19df | ||
|
|
c006fdab36 | ||
|
|
d280f0f16a | ||
|
|
b49754dc7d | ||
|
|
3302aa136b | ||
|
|
14d9b4091e | ||
|
|
aeeac6725a | ||
|
|
41b4b092b1 | ||
|
|
28186bf142 | ||
|
|
4e10d9d897 | ||
|
|
c963013858 | ||
|
|
9470ca623f | ||
|
|
2e3bc016b4 | ||
|
|
d4732130a7 | ||
|
|
853699c265 | ||
|
|
40968897a8 | ||
|
|
fdc2ba8715 | ||
|
|
3ff59eefc6 | ||
|
|
e3416abeb9 | ||
|
|
2ab2d079ab | ||
|
|
5e529969ea | ||
|
|
b7a689e349 | ||
|
|
4f4fed06e0 | ||
|
|
45fcebf9d8 | ||
|
|
e67b3bc611 | ||
|
|
d8456a0ffa | ||
|
|
73681d9b24 | ||
|
|
02ed7b2262 | ||
|
|
ab86b8cd93 | ||
|
|
3a03df8ec9 | ||
|
|
0e78b2b1f5 | ||
|
|
5b14c8c0ec | ||
|
|
0627bd09d4 | ||
|
|
a5e64e216c | ||
|
|
23cf50614f | ||
|
|
1e08ff03b3 | ||
|
|
2216385c0b |
+8
-16
@@ -11,12 +11,10 @@ jobs:
|
||||
|
||||
- run:
|
||||
name: Prepare the environment.
|
||||
command: |
|
||||
bash .circleci/prepare.sh
|
||||
command: bash .circleci/prepare.sh
|
||||
- run:
|
||||
name: Test.
|
||||
command: |
|
||||
venv/bin/python ./bin/run_tests.py
|
||||
command: venv/bin/python ./bin/run_tests.py
|
||||
|
||||
osx-python3:
|
||||
macos:
|
||||
@@ -28,12 +26,10 @@ jobs:
|
||||
|
||||
- run:
|
||||
name: Prepare the environment.
|
||||
command: |
|
||||
bash .circleci/prepare.sh
|
||||
command: bash .circleci/prepare.sh
|
||||
- run:
|
||||
name: Test.
|
||||
command: |
|
||||
venv/bin/python ./bin/run_tests.py
|
||||
command: venv/bin/python ./bin/run_tests.py
|
||||
|
||||
linux-python2:
|
||||
docker:
|
||||
@@ -46,12 +42,10 @@ jobs:
|
||||
|
||||
- run:
|
||||
name: Prepare the environment.
|
||||
command: |
|
||||
bash .circleci/prepare.sh
|
||||
command: bash .circleci/prepare.sh
|
||||
- run:
|
||||
name: Test.
|
||||
command: |
|
||||
venv/bin/python ./bin/run_tests.py
|
||||
command: venv/bin/python ./bin/run_tests.py
|
||||
|
||||
linux-python3:
|
||||
docker:
|
||||
@@ -64,12 +58,10 @@ jobs:
|
||||
|
||||
- run:
|
||||
name: Prepare the environment.
|
||||
command: |
|
||||
bash .circleci/prepare.sh
|
||||
command: bash .circleci/prepare.sh
|
||||
- run:
|
||||
name: Test.
|
||||
command: |
|
||||
venv/bin/python ./bin/run_tests.py
|
||||
command: venv/bin/python ./bin/run_tests.py
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
version: 2
|
||||
|
||||
mkdocs:
|
||||
configuration: mkdocs.yml
|
||||
|
||||
python:
|
||||
version: 3.7
|
||||
install:
|
||||
- requirements: requirements-dev.txt
|
||||
+9
-7
@@ -12,20 +12,22 @@ matrix:
|
||||
# Linux Python 3
|
||||
- sudo: required
|
||||
language: python
|
||||
python: 3.4
|
||||
python: 3.5
|
||||
services: docker
|
||||
env: PYTHON=python
|
||||
|
||||
# macOS Python 2
|
||||
- os: osx
|
||||
env: PYTHON=python2
|
||||
|
||||
# macOS Python 3
|
||||
- os: osx
|
||||
env: PYTHON=python3
|
||||
|
||||
- os: windows
|
||||
language: shell
|
||||
before_install:
|
||||
- brew update
|
||||
- brew outdated python || brew upgrade python
|
||||
- choco install python3 --version 3.6.8 --no-progress -y
|
||||
install:
|
||||
- C:\\Python36\\python -m pip install -r requirements-dev.txt
|
||||
script:
|
||||
- C:\\Python36\\python ./bin/run_tests.py
|
||||
|
||||
install: $PYTHON -m pip install -r requirements-dev.txt
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
This project is licensed under the 'BSD 2-clause license'.
|
||||
|
||||
Copyright (c) 2017, Joe Rickerby. All rights reserved.
|
||||
Copyright (c) 2017-2019, Joe Rickerby and contributors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
@@ -3,480 +3,108 @@ cibuildwheel
|
||||
|
||||
[](https://pypi.python.org/pypi/cibuildwheel) [](https://travis-ci.org/joerick/cibuildwheel) [](https://ci.appveyor.com/project/joerick/cibuildwheel/branch/master) [](https://circleci.com/gh/joerick/cibuildwheel)
|
||||
|
||||
[Documentation](https://cibuildwheel.readthedocs.org)
|
||||
|
||||
<!--intro-start-->
|
||||
|
||||
Python wheels are great. Building them across **Mac, Linux, Windows**, on **multiple versions of Python**, is not.
|
||||
|
||||
`cibuildwheel` is here to help. `cibuildwheel` runs on your CI server - currently it supports Azure Pipelines, Travis CI, Appveyor, and CircleCI - and it builds and tests your wheels across all of your platforms.
|
||||
`cibuildwheel` is here to help. `cibuildwheel` runs on your CI server - currently it supports Azure Pipelines, Travis CI, AppVeyor, and CircleCI - and it builds and tests your wheels across all of your platforms.
|
||||
|
||||
**`cibuildwheel` is in beta**. It's brand new - I'd love for you to try it and help make it better!
|
||||
|
||||
What does it do?
|
||||
----------------
|
||||
|
||||
| | macOS 10.6+ | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit |
|
||||
|---|---|---|---|---|---|
|
||||
| Python 2.7 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.4 | ✅ | ✅ | ✅ | ✅* | ✅* |
|
||||
| Python 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| | macOS 10.6+ intel | macOS 10.9+ x86_64 | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit |
|
||||
|---|---|---|---|---|---|---|
|
||||
| Python 2.7 | ✅ | | ✅ | ✅ | ✅¹ | ✅¹ |
|
||||
| Python 3.5 | ✅ | | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.6 | ✅ | | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.7 | ✅ | | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.8 | | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
|
||||
> \* Not supported on Azure Pipelines
|
||||
> ¹ Not supported on Travis
|
||||
|
||||
- Builds manylinux, macOS and Windows (32 and 64bit) wheels using Azure Pipelines, Travis CI, Appveyor, and CircleCI
|
||||
- Builds manylinux, macOS and Windows (32 and 64bit) wheels 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)
|
||||
- Runs the library test suite against the wheel-installed version of your library
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
`cibuildwheel` currently works **Travis CI** and **CircleCI** to build Linux and Mac wheels, and **Appveyor** to build Windows wheels. **Azure Pipelines** supports all three.
|
||||
`cibuildwheel` currently works on **Travis CI** and **Azure Pipelines** to build wheels for all three supported platforms (Linux, macOS, Windows). On **CircleCI** Linux and macOS wheels can be built, and on **AppVeyor** Windows is supported.
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
|-----------------|-------|-------|---------|
|
||||
| Azure Pipelines | ✅ | ✅ | ✅ |
|
||||
| Travis CI | ✅ | ✅ | |
|
||||
| Appveyor | | | ✅ |
|
||||
| Travis CI | ✅ | ✅ | ✅ |
|
||||
| AppVeyor | | | ✅ |
|
||||
| CircleCI | ✅ | ✅ | |
|
||||
|
||||
`cibuildwheel` is not intended to run on your development machine. It will try to install packages globally; this is no good. Travis CI, CircleCI, and Appveyor run their builds in isolated environments, so are ideal for this kind of script.
|
||||
`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.
|
||||
|
||||
### Minimal setup
|
||||
<!--intro-end-->
|
||||
|
||||
<details>
|
||||
<summary><b>Azure Pipelines</b>
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/apple.svg" />
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/windows.svg" />
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/linux.svg" />
|
||||
</summary>
|
||||
Example setup
|
||||
-------------
|
||||
|
||||
- Using Azure pipelines, you can build all three platforms on the same service. Create a `azure-pipelines.yml` file in your repo.
|
||||
To build manylinux and macOS wheels on Travis CI, and upload them to PyPI whenever you tag a version, you could use this `.travis.yml`:
|
||||
|
||||
**azure-pipelines.yml**
|
||||
```yaml
|
||||
jobs:
|
||||
- job: linux
|
||||
pool: {vmImage: 'Ubuntu-16.04'}
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
- bash: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install cibuildwheel==0.10.1
|
||||
cibuildwheel --output-dir wheelhouse .
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs: {pathtoPublish: 'wheelhouse'}
|
||||
- job: macos
|
||||
pool: {vmImage: 'macOS-10.13'}
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
- bash: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install cibuildwheel==0.10.1
|
||||
cibuildwheel --output-dir wheelhouse .
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs: {pathtoPublish: 'wheelhouse'}
|
||||
- job: windows
|
||||
pool: {vmImage: 'vs2017-win2016'}
|
||||
steps:
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '2.7', architecture: x86}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '2.7', architecture: x64}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.5', architecture: x86}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.5', architecture: x64}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.6', architecture: x86}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.6', architecture: x64}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.7', architecture: x86}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.7', architecture: x64}}
|
||||
- script: choco install vcpython27 -f -y
|
||||
displayName: Install Visual C++ for Python 2.7
|
||||
- bash: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install cibuildwheel==0.10.1
|
||||
cibuildwheel --output-dir wheelhouse .
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs: {pathtoPublish: 'wheelhouse'}
|
||||
language: python
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# perform a linux build
|
||||
- sudo: required
|
||||
services:
|
||||
- docker
|
||||
env: PIP=pip
|
||||
# and a mac build
|
||||
- os: osx
|
||||
language: generic
|
||||
env: PIP=pip2
|
||||
|
||||
env:
|
||||
global:
|
||||
- TWINE_USERNAME=joerick
|
||||
# Note: TWINE_PASSWORD is set in Travis settings
|
||||
|
||||
script:
|
||||
- $PIP install cibuildwheel==1.0.0
|
||||
|
||||
# build the wheels, put them into './wheelhouse'
|
||||
- cibuildwheel --output-dir wheelhouse
|
||||
|
||||
# if the release was tagged, upload them to PyPI
|
||||
- |
|
||||
if [[ $TRAVIS_TAG ]]; then
|
||||
python -m pip install twine
|
||||
python -m twine upload wheelhouse/*.whl
|
||||
fi
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Travis CI</b>
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/apple.svg" />
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/linux.svg" />
|
||||
</summary>
|
||||
|
||||
- To build Linux and Mac wheels on Travis CI, create a `.travis.yml` file in your repo.
|
||||
|
||||
```
|
||||
language: python
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- sudo: required
|
||||
services:
|
||||
- docker
|
||||
env: PIP=pip
|
||||
- os: osx
|
||||
language: generic
|
||||
env: PIP=pip2
|
||||
|
||||
script:
|
||||
- $PIP install cibuildwheel==0.11.1
|
||||
- cibuildwheel --output-dir wheelhouse
|
||||
```
|
||||
|
||||
Then setup a deployment method by following the [Travis CI deployment docs](https://docs.travis-ci.com/user/deployment/), or see [Delivering to PyPI](#delivering-to-pypi) below.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>CircleCI</b>
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/apple.svg" />
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/linux.svg" />
|
||||
</summary>
|
||||
|
||||
- To build Linux and Mac wheels on CircleCI, create a `.circleci/config.yml` file in your repo,
|
||||
|
||||
```
|
||||
version: 2
|
||||
|
||||
jobs:
|
||||
linux-wheels:
|
||||
working_directory: ~/linux-wheels
|
||||
docker:
|
||||
- image: circleci/python:3.6
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: Build the Linux wheels.
|
||||
command: |
|
||||
pip install --user cibuildwheel
|
||||
cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
|
||||
osx-wheels:
|
||||
working_directory: ~/osx-wheels
|
||||
macos:
|
||||
xcode: "10.0.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Build the OS X wheels.
|
||||
command: |
|
||||
pip install --user cibuildwheel
|
||||
cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
all-tests:
|
||||
jobs:
|
||||
- linux-wheels
|
||||
- osx-wheels
|
||||
```
|
||||
|
||||
Note: CircleCI doesn't enable free macOS containers for open source by default, but you can ask for access. See [here](https://circleci.com/docs/2.0/oss/#overview) for more information.
|
||||
|
||||
CircleCI will store the built wheels for you - you can access them from the project console.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Appveyor</b>
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/windows.svg" />
|
||||
</summary>
|
||||
|
||||
- To build Windows wheels on Appveyor, create an `appveyor.yml` file in your repo.
|
||||
|
||||
```
|
||||
build_script:
|
||||
- pip install cibuildwheel==0.11.1
|
||||
- cibuildwheel --output-dir wheelhouse
|
||||
artifacts:
|
||||
- path: "wheelhouse\\*.whl"
|
||||
name: Wheels
|
||||
```
|
||||
|
||||
Appveyor will store the built wheels for you - you can access them from the project console. Alternatively, you may want to store them in the same place as the Travis CI build. See [Appveyor deployment docs](https://www.appveyor.com/docs/deployment/) for more info, or see [Delivering to PyPI](#delivering-to-pypi) below.
|
||||
|
||||
</details>
|
||||
|
||||
- Commit those files, enable building of your repo on Travis CI and Appveyor, and push.
|
||||
|
||||
All being well, you should get wheels delivered to you in a few minutes.
|
||||
|
||||
> ⚠️ Got an error? Check the [checklist](#it-didnt-work) below.
|
||||
|
||||
### Configuration overview
|
||||
|
||||
`cibuildwheel` allows for easy customization of the various phases of the build process demonstrated above:
|
||||
|
||||
| | Option | |
|
||||
|---|---|---|
|
||||
| **Target wheels** | `CIBW_PLATFORM` | Override the auto-detected target platform |
|
||||
| | `CIBW_BUILD` | Build only certain Python versions |
|
||||
| | `CIBW_SKIP` | Skip certain Python versions |
|
||||
| **Build parameters** | `CIBW_BUILD_VERBOSITY` | Increase or decrease the output of `pip wheel` |
|
||||
| **Build environment** | `CIBW_ENVIRONMENT` | Set environment variables needed during the build |
|
||||
| | `CIBW_BEFORE_BUILD` | Execute a shell command preparing each wheel's build |
|
||||
| | `CIBW_MANYLINUX1_X86_64_IMAGE` | Specify an alternative manylinx1 x86_64 docker image |
|
||||
| | `CIBW_MANYLINUX1_I686_IMAGE` | Specify an alternative manylinux1 i686 docker image |
|
||||
| **Tests** | `CIBW_TEST_COMMAND` | Execute a shell command to test all built wheels |
|
||||
| | `CIBW_TEST_REQUIRES` | Install Python dependencies before running the tests |
|
||||
|
||||
A more detailed description of the options, the allowed values, and some examples can be found in the [Options](#options) section.
|
||||
|
||||
### Linux builds on Docker
|
||||
|
||||
Linux wheels are built in the [`manylinux1` docker images](https://github.com/pypa/manylinux) to provide binary compatible wheels on Linux, according to [PEP 513](https://www.python.org/dev/peps/pep-0513/). Because of this, when building with `cibuildwheel` on Linux, a few things should be taken into account:
|
||||
- Programs and libraries cannot be installed on the Travis CI Ubuntu host with `apt-get`, but can be installed inside of the Docker image using `yum` or manually. The same goes for environment variables that are potentially needed to customize the wheel building. `cibuildwheel` supports this by providing the `CIBW_ENVIRONMENT` and `CIBW_BEFORE_BUILD` options to setup the build environment inside the running Docker image. See [below](#options) for details on these options.
|
||||
- The project directory is mounted in the running Docker instance as `/project`, the output directory for the wheels as `/output`. In general, this is handled transparently by `cibuildwheel`. For a more finegrained level of control however, the root of the host file system is mounted as `/host`, allowing for example to access shared files, caches, etc. on the host file system. Note that this is not available on CircleCI due to their Docker policies.
|
||||
- Alternative dockers images can be specified with the `CIBW_MANYLINUX1_X86_64_IMAGE` and `CIBW_MANYLINUX1_I686_IMAGE` options to allow for a custom, preconfigured build environment for the Linux builds. See [below](#options) for more details.
|
||||
|
||||
For more information, including how to build on Appveyor, Azure, CircleCI, check out the [documentation](https://cibuildwheel.readthedocs.org).
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
```
|
||||
usage: cibuildwheel [-h] [--platform {auto,linux,macos,windows}]
|
||||
[--output-dir OUTPUT_DIR] [--print-build-identifiers]
|
||||
[project_dir]
|
||||
|
||||
Build wheels for all the platforms.
|
||||
|
||||
positional arguments:
|
||||
project_dir Path to the project that you want wheels for.
|
||||
Default: the current directory.
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--platform {auto,linux,macos,windows}
|
||||
Platform to build for. For "linux" you need docker
|
||||
running, on Mac or Linux. For "macos", you need a Mac
|
||||
machine, and note that this script is going to
|
||||
automatically install MacPython on your system, so
|
||||
don't run on your development machine. For "windows",
|
||||
you need to run in Windows, and it will build and test
|
||||
for all versions of Python at C:\PythonXX[-x64].
|
||||
--output-dir OUTPUT_DIR
|
||||
Destination folder for the wheels.
|
||||
--print-build-identifiers
|
||||
Print the build identifiers matched by the current
|
||||
invocation and exit.
|
||||
|
||||
```
|
||||
|
||||
Most of the config is via environment variables. These go into `.travis.yml`, `appveyor.yml`, and `.circleci/config.yml` nicely.
|
||||
|
||||
***
|
||||
|
||||
| Environment variable: `CIBW_PLATFORM` | Command line argument: `--platform`
|
||||
| --- | ---
|
||||
|
||||
Options: `auto` `linux` `macos` `windows`
|
||||
|
||||
Default: `auto`
|
||||
|
||||
`auto` will auto-detect platform using environment variables, such as `TRAVIS_OS_NAME`/`APPVEYOR`/`CIRCLECI`.
|
||||
|
||||
For `linux` you need Docker running, on Mac or Linux. For `macos`, you need a Mac machine, and note that this script is going to automatically install MacPython on your system, so don't run on your development machine. For `windows`, you need to run in Windows, and it will build and test for all versions of Python at `C:\PythonXX[-x64]`.
|
||||
|
||||
***
|
||||
|
||||
| Environment variables: `CIBW_BUILD` and `CIBW_SKIP`
|
||||
| ---
|
||||
|
||||
Optional.
|
||||
|
||||
Space-separated list of builds to build and skip. Each build has an identifier like `cp27-manylinux1_x86_64` or `cp34-macosx_10_6_intel` - you can list specific ones to build and `cibuildwheel` will only build those, and/or list ones to skip and `cibuildwheel` won't try to build them.
|
||||
|
||||
When both options are specified, both conditions are applied and only builds with a tag that matches `CIBW_BUILD` and does not match `CIBW_SKIP` will be built.
|
||||
|
||||
The format is `python_tag-platform_tag`. The tags are as defined in [PEP 0425](https://www.python.org/dev/peps/pep-0425/#details).
|
||||
|
||||
Python tags look like `cp27` `cp34` `cp35` `cp36` `cp37`
|
||||
|
||||
Platform tags look like `macosx_10_6_intel` `manylinux1_x86_64` `manylinux1_i686` `win32` `win_amd64`
|
||||
|
||||
You can also use shell-style globbing syntax (as per `fnmatch`)
|
||||
|
||||
Examples:
|
||||
- Only build on Python 3.6: `CIBW_BUILD`:`cp36-*`
|
||||
- Skip building on Python 2.7 on the Mac: `CIBW_SKIP`:`cp27-macosx_10_6_intel`
|
||||
- Skip building on Python 2.7 on all platforms: `CIBW_SKIP`:`cp27-*`
|
||||
- Skip Python 2.7 on Windows: `CIBW_SKIP`:`cp27-win*`
|
||||
- Skip Python 2.7 on 32-bit Windows: `CIBW_SKIP`:`cp27-win32`
|
||||
- Skip Python 3.4 and Python 3.5: `CIBW_SKIP`:`cp34-* cp35-*`
|
||||
- Skip Python 3.6 on Linux: `CIBW_SKIP`:`cp36-manylinux*`
|
||||
- Only build on Python 3 and skip 32-bit builds: `CIBW_BUILD`:`cp3?-*` and `CIBW_SKIP`:`*-win32 *-manylinux1_i686`
|
||||
|
||||
***
|
||||
|
||||
| Environment variable: `CIBW_BUILD_VERBOSITY`
|
||||
| ---
|
||||
|
||||
Optional.
|
||||
|
||||
An number from 1 to 3 to increase the level of verbosity (corresponding to invoking pip with `-v`, `-vv`, and `-vvv`), between -1 and -3 (`-q`, `-qq`, and `-qqq`), or just 0 (default verbosity). These flags are useful while debugging a build when the output of the actual build invoked by `pip wheel` is required.
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_BUILD_VERBOSITY_MACOS` | `CIBW_BUILD_VERBOSITY_WINDOWS` | `CIBW_BUILD_VERBOSITY_LINUX`
|
||||
|
||||
***
|
||||
|
||||
| Environment variable: `CIBW_ENVIRONMENT`
|
||||
| ---
|
||||
|
||||
Optional.
|
||||
|
||||
A space-separated list of environment variables to set during the build. Bash syntax should be used (even on Windows!).
|
||||
|
||||
You must set this variable to pass variables to Linux builds (since they execute in a Docker container). It also works for the other platforms.
|
||||
|
||||
You can use `$PATH` syntax to insert other variables, or the `$(pwd)` syntax to insert the output of other shell commands.
|
||||
|
||||
Example: `CFLAGS="-g -Wall" CXXFLAGS="-Wall"`
|
||||
Example: `PATH=$PATH:/usr/local/bin`
|
||||
Example: `BUILD_TIME="$(date)"`
|
||||
Example: `PIP_EXTRA_INDEX_URL="https://pypi.myorg.com/simple"`
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_ENVIRONMENT_MACOS` | `CIBW_ENVIRONMENT_WINDOWS` | `CIBW_ENVIRONMENT_LINUX`
|
||||
|
||||
In addition to the above, `cibuildwheel` always defines the environment variable `CIBUILDWHEEL=1`. This can be useful for [building wheels with optional extensions](https://github.com/joerick/cibuildwheel/wiki/Building-packages-with-optional-C-extensions).
|
||||
|
||||
***
|
||||
|
||||
| Environment variable: `CIBW_BEFORE_BUILD`
|
||||
| ---
|
||||
|
||||
Optional.
|
||||
|
||||
A shell command to run before building the wheel. This option allows you to run a command in **each** Python environment before the `pip wheel` command. This is useful if you need to set up some dependency so it's available during the build.
|
||||
|
||||
If dependencies are required to build your wheel (for example if you include a header from a Python module), set this to `pip install .`, and the dependencies will be installed automatically by pip. However, this means your package will be built twice - if your package takes a long time to build, you might wish to manually list the dependencies here instead.
|
||||
|
||||
The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root.
|
||||
|
||||
Example: `pip install .`
|
||||
Example: `pip install pybind11`
|
||||
Example: `yum install -y libffi-dev && pip install .`
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_BEFORE_BUILD_MACOS` | `CIBW_BEFORE_BUILD_WINDOWS` | `CIBW_BEFORE_BUILD_LINUX`
|
||||
|
||||
***
|
||||
|
||||
| Environment variables: `CIBW_MANYLINUX1_X86_64_IMAGE` and `CIBW_MANYLINUX1_I686_IMAGE`
|
||||
| ---
|
||||
|
||||
Optional.
|
||||
|
||||
An alternative docker image to be used for building [`manylinux1`](https://github.com/pypa/manylinux) wheels. `cibuildwheel` will then pull these instead of the official images, [`quay.io/pypa/manylinux1_x86_64`](https://quay.io/pypa/manylinux1_i686) and [`quay.io/pypa/manylinux1_i686`](https://quay.io/pypa/manylinux1_i686).
|
||||
|
||||
Beware to specify a valid docker image that can be used the same as the official, default docker images: all necessary Python and pip versions need to be present in `/opt/python/`, and the `auditwheel` tool needs to be present for `cibuildwheel` to work. Apart from that, the architecture and relevant shared system libraries need to be manylinux1-compatible in order to produce valid `manylinux1` wheels (see https://github.com/pypa/manylinux and [PEP 513](https://www.python.org/dev/peps/pep-0513/) for more details).
|
||||
|
||||
Example: `dockcross/manylinux-x64`
|
||||
Example: `dockcross/manylinux-x86`
|
||||
|
||||
***
|
||||
|
||||
| Environment variable: `CIBW_TEST_COMMAND`
|
||||
| ---
|
||||
|
||||
Optional.
|
||||
|
||||
Shell command to run tests after the build. The wheel will be installed automatically and available for import from the tests. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`.
|
||||
|
||||
On Linux and Mac, the command runs in a shell, so you can write things like `cmd1 && cmd2`.
|
||||
|
||||
Example: `nosetests {project}/tests`
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_TEST_COMMAND_MACOS` | `CIBW_TEST_COMMAND_WINDOWS` | `CIBW_TEST_COMMAND_LINUX`
|
||||
|
||||
***
|
||||
|
||||
| Environment variable: `CIBW_TEST_REQUIRES`
|
||||
| ---
|
||||
|
||||
Optional.
|
||||
|
||||
Space-separated list of dependencies required for running the tests.
|
||||
|
||||
Example: `pytest`
|
||||
Example: `nose==1.3.7 moto==0.4.31`
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_TEST_REQUIRES_MACOS` | `CIBW_TEST_REQUIRES_WINDOWS` | `CIBW_TEST_REQUIRES_LINUX`
|
||||
|
||||
|
||||
### Example YML syntax
|
||||
|
||||
<table>
|
||||
<tr><td><i>example .travis.yml environment variables</i><pre><code>env:
|
||||
global:
|
||||
- CIBW_TEST_REQUIRES=nose
|
||||
- CIBW_TEST_COMMAND="nosetests {project}/tests"
|
||||
</code></pre></td>
|
||||
<td><i>example appveyor.yml environment variables</i><pre><code>environment:
|
||||
global:
|
||||
CIBW_TEST_REQUIRES: nose
|
||||
CIBW_TEST_COMMAND: "nosetests {project}\\tests"
|
||||
</code></pre></td>
|
||||
</tr></table>
|
||||
|
||||
Delivering to PyPI
|
||||
------------------
|
||||
|
||||
After you've built your wheels, you'll probably want to deliver them to PyPI.
|
||||
|
||||
### Manual method
|
||||
|
||||
On your development machine, do the following...
|
||||
|
||||
```bash
|
||||
# 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. Put
|
||||
# them all into the 'dist' folder.
|
||||
|
||||
# Upload using 'twine' (you may need to 'pip install twine')
|
||||
twine upload dist/*
|
||||
```
|
||||
|
||||
### Semi-automatic method using wheelhouse-uploader
|
||||
|
||||
Obviously, manual steps are for chumps, so we can automate this a little by using [wheelhouse-uploader](https://github.com/ogrisel/wheelhouse-uploader).
|
||||
|
||||
> Quick note from me - using S3 as a storage didn't work due to a [bug](https://issues.apache.org/jira/browse/LIBCLOUD-792) in libcloud. Feel free to use my fork of that package that fixes the bug `pip install https://github.com/joerick/libcloud/archive/v1.5.0-s3fix.zip`
|
||||
|
||||
### Automatic method
|
||||
|
||||
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 any cloud storage to work - you just need to bump the version and tag it.
|
||||
|
||||
Check out [this example repo](https://github.com/joerick/cibuildwheel-autopypi-example) for instructions on how to set this up.
|
||||
|
||||
It didn't work!
|
||||
---------------
|
||||
|
||||
If your wheel didn't compile, check the list below for some debugging tips.
|
||||
|
||||
- A mistake in your config. To quickly test your config without doing a git push and waiting for your code to build on CI, you can run the Linux build in a Docker container. On Mac or Linux, with Docker running, try `cibuildwheel --platform linux`. You'll have to bring your config into the current environment first.
|
||||
- Missing dependency. You might need to install something on the build machine. You can do this in `.travis.yml`, `appveyor.yml`, or `.circleci/config.yml`, with apt-get, brew or whatever Windows uses :P . Given how the Linux build works, we'll probably have to build something into `cibuildwheel`. Let's chat about that over in the issues!
|
||||
- Windows: missing C feature. The Windows C compiler doesn't support C language features invented after 1990, so you'll have to backport your C code to C90. For me, this mostly involved putting my variable declarations at the top of the function like an animal.
|
||||
- MacOS: calling cibuildwheel from a python3 script and getting a `ModuleNotFoundError`? Due to a [bug](https://bugs.python.org/issue22490) in CPython, you'll need to [unset the `__PYVENV_LAUNCHER__` variable](https://github.com/joerick/cibuildwheel/issues/133#issuecomment-478288597) before activating a venv.
|
||||
| | Option | Description |
|
||||
|---|--------|-------------|
|
||||
| **Build selection** | [`CIBW_PLATFORM`](https://cibuildwheel.readthedocs.io/en/stable/options/#platform) | Override the auto-detected target platform |
|
||||
| | [`CIBW_BUILD`](https://cibuildwheel.readthedocs.io/en/stable/options/#build-skip) [`CIBW_SKIP`](https://cibuildwheel.readthedocs.io/en/stable/options/#build-skip) | Choose the Python versions to build |
|
||||
| **Build environment** | [`CIBW_ENVIRONMENT`](https://cibuildwheel.readthedocs.io/en/stable/options/#environment) | Set environment variables needed during the build |
|
||||
| | [`CIBW_BEFORE_BUILD`](https://cibuildwheel.readthedocs.io/en/stable/options/#before-build) | Execute a shell command preparing each wheel's build |
|
||||
| | [`CIBW_MANYLINUX_X86_64_IMAGE`](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) [`CIBW_MANYLINUX_I686_IMAGE`](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) | Specify alternative manylinux docker images |
|
||||
| **Testing** | [`CIBW_TEST_COMMAND`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-command) | Execute a shell command to test all built wheels |
|
||||
| | [`CIBW_TEST_REQUIRES`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-requires) | Install Python dependencies before running the tests |
|
||||
| | [`CIBW_TEST_EXTRAS`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Install your wheel for testing using extras_require |
|
||||
| **Other** | [`CIBW_BUILD_VERBOSITY`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-extras) | Increase/decrease the output of pip wheel |
|
||||
|
||||
Working examples
|
||||
----------------
|
||||
|
||||
Here are some repos that use cibuildwheel.
|
||||
Here are some repos that use cibuildwheel.
|
||||
|
||||
- [pyinstrument_cext](https://github.com/joerick/pyinstrument_cext)
|
||||
- [websockets](https://github.com/aaugustin/websockets)
|
||||
@@ -486,13 +114,15 @@ Here are some repos that use cibuildwheel.
|
||||
- [KDEpy](https://github.com/tommyod/KDEpy)
|
||||
- [AutoPy](https://github.com/autopilot-rs/autopy)
|
||||
- [apriltags2-ethz](https://github.com/safijari/apriltags2_ethz)
|
||||
- [TgCrypto](https://github.com/pyrogram/tgcrypto)
|
||||
- [Twisted](https://github.com/twisted/twisted)
|
||||
|
||||
> Add repo here! Send a PR.
|
||||
> Add your repo here! Send a PR.
|
||||
|
||||
Legal note
|
||||
----------
|
||||
|
||||
Since `cibuildwheel` runs the wheel through delocate or auditwheel, it might automatically bundle dynamically linked libraries from the build machine.
|
||||
Since `cibuildwheel` runs the wheel through delocate or auditwheel, it might automatically bundle dynamically linked libraries from the build machine.
|
||||
|
||||
It helps ensure that the library can run without any dependencies outside of the pip toolchain.
|
||||
|
||||
@@ -501,13 +131,30 @@ This is similar to static linking, so it might have some licence implications. C
|
||||
Changelog
|
||||
=========
|
||||
|
||||
### 0.12.0
|
||||
|
||||
_29 September 2019_
|
||||
|
||||
- ✨ Add CIBW_TEST_EXTRAS option, to allow testing using extra_require
|
||||
options. For example, set `CIBW_TEST_EXTRAS=test,qt` to make the wheel
|
||||
installed with `pip install <wheel_file>[test,qt]`
|
||||
- 🛠 Update Python from 3.7.2 to 3.7.4 on macOS
|
||||
- 🛠 Update OpenSSL patch to 1.0.2t on macOS
|
||||
|
||||
### 0.11.1
|
||||
|
||||
_28 May 2019_
|
||||
|
||||
- 🐛 Fix missing file in the release tarball, that was causing problems with
|
||||
Windows builds (#141)
|
||||
|
||||
### 0.11.0
|
||||
|
||||
_26 May 2019_
|
||||
|
||||
- ✨ Add support for building on Azure pipelines! This lets you build all
|
||||
Linux, Mac and Windows wheels on one service, so it promises to be the
|
||||
easiest to set up! Check out the quickstart in the docs, or
|
||||
easiest to set up! Check out the quickstart in the docs, or
|
||||
[cibuildwheel-azure-example](https://github.com/joerick/cibuildwheel-azure-example)
|
||||
for an example project. (#126, #132)
|
||||
- 🛠 Internal change - the end-to-end test projects format was updated, so we
|
||||
@@ -622,7 +269,7 @@ _7 September 2017_
|
||||
_14 August 2017_
|
||||
|
||||
- 🐛 Fixed a bug on Windows where subprocess' output was hidden (#23)
|
||||
- 🐛 Fixed a bug on Appveyor where logs would appear in the wrong order due to output buffering (#24, thanks @YannickJadoul!)
|
||||
- 🐛 Fixed a bug on AppVeyor where logs would appear in the wrong order due to output buffering (#24, thanks @YannickJadoul!)
|
||||
|
||||
### 0.4.0
|
||||
|
||||
@@ -647,7 +294,7 @@ _11 June 2017_
|
||||
|
||||
_13 April 2017_
|
||||
|
||||
- ✨ Added `CIBW_SKIP` option, letting users explicitly skip a build
|
||||
- ✨ Added `CIBW_SKIP` option, letting users explicitly skip a build
|
||||
- ✨ Added `CIBW_BEFORE_BUILD` option, letting users run a shell command before the build starts
|
||||
|
||||
### 0.1.3
|
||||
@@ -659,24 +306,7 @@ _31 March 2017_
|
||||
Contributing
|
||||
============
|
||||
|
||||
Wheel-building is pretty complex. I expect users to find many edge-cases - please help the rest of the community out by documenting these, adding features to support them, and reporting bugs.
|
||||
|
||||
I plan to be pretty liberal in accepting pull requests, as long as they align with the design goals below.
|
||||
|
||||
`cibuildwheel` is indie open source. I'm not paid to work on this.
|
||||
|
||||
Design Goals
|
||||
------------
|
||||
|
||||
- `cibuildwheel` should wrap the complexity of wheel building.
|
||||
- The user interface to `cibuildwheel` is the build script (e.g. `.travis.yml`). Feature additions should not increase the complexity of this script.
|
||||
- Options should be environment variables (these lend themselves better to YML config files). They should be prefixed with `CIBW_`.
|
||||
- Options should be generalise to all platforms. If platform-specific options are required, they should be namespaced e.g. `CIBW_TEST_COMMAND_MACOS`
|
||||
|
||||
Other notes:
|
||||
|
||||
- The platforms are very similar, until they're not. I'd rather have straight-forward code than totally DRY code, so let's keep airy platfrom abstractions to a minimum.
|
||||
- I might want to break the options into a shared config file one day, so that config is more easily shared. That has motivated some of the design decisions.
|
||||
For more info on how to contribute to cibuildwheel, see the [docs](https://cibuildwheel.readthedocs.io/en/latest/contributing/).
|
||||
|
||||
Maintainers
|
||||
-----------
|
||||
@@ -689,7 +319,7 @@ Maintainers
|
||||
Credits
|
||||
-------
|
||||
|
||||
`cibuildwheel` stands on the shoulders of giants.
|
||||
`cibuildwheel` stands on the shoulders of giants.
|
||||
|
||||
- ⭐️ @matthew-brett for [matthew-brett/multibuild](http://github.com/matthew-brett/multibuild) and [matthew-brett/delocate](http://github.com/matthew-brett/delocate)
|
||||
- @PyPA for the manylinux Docker images [pypa/manylinux](https://github.com/pypa/manylinux)
|
||||
@@ -702,7 +332,7 @@ Massive props also to-
|
||||
- @mayeut for a [phenomenal PR](https://github.com/joerick/cibuildwheel/pull/71) patching Python itself for better compatibility!
|
||||
|
||||
See also
|
||||
--------
|
||||
========
|
||||
|
||||
If you'd like to keep wheel building separate from the package itself, check out [astrofrog/autowheel](https://github.com/astrofrog/autowheel). It builds packages using cibuildwheel from source distributions on PyPI.
|
||||
|
||||
|
||||
+11
-12
@@ -1,31 +1,30 @@
|
||||
jobs:
|
||||
- job: linux
|
||||
pool: {vmImage: 'Ubuntu-16.04'}
|
||||
steps:
|
||||
pool: {vmImage: 'Ubuntu-18.04'}
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '3.8'
|
||||
- bash: |
|
||||
python -m pip install -r requirements-dev.txt
|
||||
python ./bin/run_tests.py
|
||||
|
||||
- job: macos
|
||||
pool: {vmImage: 'macOS-10.13'}
|
||||
steps:
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '3.8'
|
||||
- bash: |
|
||||
python -m pip install -r requirements-dev.txt
|
||||
python ./bin/run_tests.py
|
||||
|
||||
- job: windows
|
||||
pool: {vmImage: 'vs2017-win2016'}
|
||||
steps:
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '2.7', architecture: x86}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '2.7', architecture: x64}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.5', architecture: x86}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.5', architecture: x64}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.6', architecture: x86}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.6', architecture: x64}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.7', architecture: x86}}
|
||||
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.7', architecture: x64}}
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '3.8'
|
||||
- script: choco install vcpython27 -f -y
|
||||
displayName: Install Visual C++ for Python 2.7
|
||||
- bash: |
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = '0.11.1'
|
||||
__version__ = '1.0.0'
|
||||
|
||||
@@ -54,6 +54,8 @@ def main():
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
detect_obsolete_options()
|
||||
|
||||
if args.platform != 'auto':
|
||||
platform = args.platform
|
||||
else:
|
||||
@@ -63,6 +65,8 @@ def main():
|
||||
platform = 'linux'
|
||||
elif os.environ.get('TRAVIS_OS_NAME') == 'osx':
|
||||
platform = 'macos'
|
||||
elif os.environ.get('TRAVIS_OS_NAME') == 'windows':
|
||||
platform = 'windows'
|
||||
elif 'APPVEYOR' in os.environ:
|
||||
platform = 'windows'
|
||||
elif 'BITRISE_BUILD_NUMBER' in os.environ:
|
||||
@@ -82,7 +86,7 @@ def main():
|
||||
|
||||
if platform is None:
|
||||
print('cibuildwheel: Unable to detect platform. cibuildwheel should run on your CI server, '
|
||||
'Travis CI, Appveyor, and CircleCI are supported. You can run on your development '
|
||||
'Travis CI, AppVeyor, and CircleCI are supported. You can run on your development '
|
||||
'machine using the --platform argument. Check --help output for more '
|
||||
'information.',
|
||||
file=sys.stderr)
|
||||
@@ -91,12 +95,16 @@ def main():
|
||||
output_dir = args.output_dir
|
||||
test_command = get_option_from_environment('CIBW_TEST_COMMAND', platform=platform)
|
||||
test_requires = get_option_from_environment('CIBW_TEST_REQUIRES', platform=platform, default='').split()
|
||||
test_extras = get_option_from_environment('CIBW_TEST_EXTRAS', platform=platform, default='')
|
||||
project_dir = args.project_dir
|
||||
before_build = get_option_from_environment('CIBW_BEFORE_BUILD', platform=platform)
|
||||
build_verbosity = get_option_from_environment('CIBW_BUILD_VERBOSITY', platform=platform, default='')
|
||||
build_config, skip_config = os.environ.get('CIBW_BUILD', '*'), os.environ.get('CIBW_SKIP', '')
|
||||
environment_config = get_option_from_environment('CIBW_ENVIRONMENT', platform=platform, default='')
|
||||
|
||||
if test_extras:
|
||||
test_extras = '[{0}]'.format(test_extras)
|
||||
|
||||
try:
|
||||
build_verbosity = min(3, max(-3, int(build_verbosity)))
|
||||
except ValueError:
|
||||
@@ -129,6 +137,7 @@ def main():
|
||||
output_dir=output_dir,
|
||||
test_command=test_command,
|
||||
test_requires=test_requires,
|
||||
test_extras=test_extras,
|
||||
before_build=before_build,
|
||||
build_verbosity=build_verbosity,
|
||||
build_selector=build_selector,
|
||||
@@ -136,11 +145,17 @@ def main():
|
||||
)
|
||||
|
||||
if platform == 'linux':
|
||||
manylinux1_x86_64_image = os.environ.get('CIBW_MANYLINUX1_X86_64_IMAGE', None)
|
||||
manylinux1_i686_image = os.environ.get('CIBW_MANYLINUX1_I686_IMAGE', None)
|
||||
manylinux_x86_64_image = os.environ.get('CIBW_MANYLINUX_X86_64_IMAGE', 'manylinux2010')
|
||||
manylinux_i686_image = os.environ.get('CIBW_MANYLINUX_I686_IMAGE', 'manylinux2010')
|
||||
|
||||
default_manylinux_images_x86_64 = {'manylinux1': 'quay.io/pypa/manylinux1_x86_64',
|
||||
'manylinux2010': 'quay.io/pypa/manylinux2010_x86_64'}
|
||||
default_manylinux_images_i686 = {'manylinux1': 'quay.io/pypa/manylinux1_i686',
|
||||
'manylinux2010': 'quay.io/pypa/manylinux2010_i686'}
|
||||
|
||||
build_options.update(
|
||||
manylinux1_images={'x86_64': manylinux1_x86_64_image, 'i686': manylinux1_i686_image},
|
||||
manylinux_images={'x86_64': default_manylinux_images_x86_64.get(manylinux_x86_64_image) or manylinux_x86_64_image,
|
||||
'i686': default_manylinux_images_i686.get(manylinux_i686_image) or manylinux_i686_image},
|
||||
)
|
||||
elif platform == 'macos':
|
||||
pass
|
||||
@@ -165,6 +180,26 @@ def main():
|
||||
raise Exception('Unsupported platform')
|
||||
|
||||
|
||||
def detect_obsolete_options():
|
||||
# Check the old 'MANYLINUX1_*_IMAGE' options
|
||||
for (deprecated, alternative) in [('CIBW_MANYLINUX1_X86_64_IMAGE', 'CIBW_MANYLINUX_X86_64_IMAGE'),
|
||||
('CIBW_MANYLINUX1_I686_IMAGE', 'CIBW_MANYLINUX_I686_IMAGE')]:
|
||||
if deprecated in os.environ:
|
||||
print("'{}' has been deprecated, and will be removed in a future release. Use the option '{}' instead.".format(deprecated, alternative))
|
||||
if alternative not in os.environ:
|
||||
print("Using value of option '{}' as replacement for '{}'".format(deprecated, alternative))
|
||||
os.environ[alternative] = os.environ[deprecated]
|
||||
else:
|
||||
print("Option '{}' is not empty. Please unset '{}'".format(alternative, deprecated))
|
||||
exit(2)
|
||||
|
||||
# Check for 'manylinux1' in the 'CIBW_BUILD' and 'CIBW_SKIP' options
|
||||
for deprecated in ['CIBW_BUILD', 'CIBW_SKIP']:
|
||||
if deprecated in os.environ and 'manylinux1' in os.environ[deprecated]:
|
||||
print("Build identifiers with 'manylinux1' been deprecated. Replacing all occurences of 'manylinux1' by 'manylinux' in the option '{}'".format(deprecated))
|
||||
os.environ[deprecated] = os.environ[deprecated].replace('manylinux1', 'manylinux')
|
||||
|
||||
|
||||
def print_preamble(platform, build_options):
|
||||
print(textwrap.dedent('''
|
||||
_ _ _ _ _ _ _
|
||||
|
||||
+61
-34
@@ -12,25 +12,25 @@ except ImportError:
|
||||
def get_python_configurations(build_selector):
|
||||
PythonConfiguration = namedtuple('PythonConfiguration', ['identifier', 'path'])
|
||||
python_configurations = [
|
||||
PythonConfiguration(identifier='cp27-manylinux1_x86_64', path='/opt/python/cp27-cp27m'),
|
||||
PythonConfiguration(identifier='cp27-manylinux1_x86_64', path='/opt/python/cp27-cp27mu'),
|
||||
PythonConfiguration(identifier='cp34-manylinux1_x86_64', path='/opt/python/cp34-cp34m'),
|
||||
PythonConfiguration(identifier='cp35-manylinux1_x86_64', path='/opt/python/cp35-cp35m'),
|
||||
PythonConfiguration(identifier='cp36-manylinux1_x86_64', path='/opt/python/cp36-cp36m'),
|
||||
PythonConfiguration(identifier='cp37-manylinux1_x86_64', path='/opt/python/cp37-cp37m'),
|
||||
PythonConfiguration(identifier='cp27-manylinux1_i686', path='/opt/python/cp27-cp27m'),
|
||||
PythonConfiguration(identifier='cp27-manylinux1_i686', path='/opt/python/cp27-cp27mu'),
|
||||
PythonConfiguration(identifier='cp34-manylinux1_i686', path='/opt/python/cp34-cp34m'),
|
||||
PythonConfiguration(identifier='cp35-manylinux1_i686', path='/opt/python/cp35-cp35m'),
|
||||
PythonConfiguration(identifier='cp36-manylinux1_i686', path='/opt/python/cp36-cp36m'),
|
||||
PythonConfiguration(identifier='cp37-manylinux1_i686', path='/opt/python/cp37-cp37m'),
|
||||
PythonConfiguration(identifier='cp27-manylinux_x86_64', path='/opt/python/cp27-cp27m'),
|
||||
PythonConfiguration(identifier='cp27-manylinux_x86_64', path='/opt/python/cp27-cp27mu'),
|
||||
PythonConfiguration(identifier='cp35-manylinux_x86_64', path='/opt/python/cp35-cp35m'),
|
||||
PythonConfiguration(identifier='cp36-manylinux_x86_64', path='/opt/python/cp36-cp36m'),
|
||||
PythonConfiguration(identifier='cp37-manylinux_x86_64', path='/opt/python/cp37-cp37m'),
|
||||
PythonConfiguration(identifier='cp38-manylinux_x86_64', path='/opt/python/cp38-cp38'),
|
||||
PythonConfiguration(identifier='cp27-manylinux_i686', path='/opt/python/cp27-cp27m'),
|
||||
PythonConfiguration(identifier='cp27-manylinux_i686', path='/opt/python/cp27-cp27mu'),
|
||||
PythonConfiguration(identifier='cp35-manylinux_i686', path='/opt/python/cp35-cp35m'),
|
||||
PythonConfiguration(identifier='cp36-manylinux_i686', path='/opt/python/cp36-cp36m'),
|
||||
PythonConfiguration(identifier='cp37-manylinux_i686', path='/opt/python/cp37-cp37m'),
|
||||
PythonConfiguration(identifier='cp38-manylinux_i686', path='/opt/python/cp38-cp38'),
|
||||
]
|
||||
|
||||
# skip builds as required
|
||||
return [c for c in python_configurations if build_selector(c.identifier)]
|
||||
|
||||
|
||||
def build(project_dir, output_dir, test_command, test_requires, before_build, build_verbosity, build_selector, environment, manylinux1_images):
|
||||
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment, manylinux_images):
|
||||
try:
|
||||
subprocess.check_call(['docker', '--version'])
|
||||
except:
|
||||
@@ -42,8 +42,8 @@ def build(project_dir, output_dir, test_command, test_requires, before_build, bu
|
||||
|
||||
python_configurations = get_python_configurations(build_selector)
|
||||
platforms = [
|
||||
('manylinux1_x86_64', manylinux1_images.get('x86_64') or 'quay.io/pypa/manylinux1_x86_64'),
|
||||
('manylinux1_i686', manylinux1_images.get('i686') or 'quay.io/pypa/manylinux1_i686'),
|
||||
('manylinux_x86_64', manylinux_images['x86_64']),
|
||||
('manylinux_i686', manylinux_images['i686']),
|
||||
]
|
||||
|
||||
for platform_tag, docker_image in platforms:
|
||||
@@ -62,9 +62,9 @@ def build(project_dir, output_dir, test_command, test_requires, before_build, bu
|
||||
for PYBIN in {pybin_paths}; do
|
||||
# Setup
|
||||
rm -rf /tmp/built_wheel
|
||||
rm -rf /tmp/delocated_wheel
|
||||
rm -rf /tmp/delocated_wheels
|
||||
mkdir /tmp/built_wheel
|
||||
mkdir /tmp/delocated_wheel
|
||||
mkdir /tmp/delocated_wheels
|
||||
|
||||
if [ ! -z {before_build} ]; then
|
||||
PATH="$PYBIN:$PATH" sh -c {before_build}
|
||||
@@ -79,34 +79,61 @@ def build(project_dir, output_dir, test_command, test_requires, before_build, bu
|
||||
# the first element
|
||||
if [[ "$built_wheel" == *none-any.whl ]]; then
|
||||
# pure python wheel - just copy
|
||||
mv "$built_wheel" /tmp/delocated_wheel
|
||||
mv "$built_wheel" /tmp/delocated_wheels
|
||||
else
|
||||
auditwheel repair "$built_wheel" -w /tmp/delocated_wheel
|
||||
auditwheel repair "$built_wheel" -w /tmp/delocated_wheels
|
||||
fi
|
||||
delocated_wheel=(/tmp/delocated_wheel/*.whl)
|
||||
delocated_wheels=(/tmp/delocated_wheels/*.whl)
|
||||
|
||||
# Install the wheel we just built
|
||||
"$PYBIN/pip" install "$delocated_wheel"
|
||||
|
||||
# Install any requirements to run the tests
|
||||
if [ ! -z "{test_requires}" ]; then
|
||||
"$PYBIN/pip" install {test_requires}
|
||||
fi
|
||||
|
||||
# Run the tests from a different directory
|
||||
if [ ! -z {test_command} ]; then
|
||||
pushd $HOME
|
||||
PATH="$PYBIN:$PATH" sh -c {test_command}
|
||||
popd
|
||||
# Set up a virtual environment to install and test from, to make sure
|
||||
# there are no dependencies that were pulled in at build time.
|
||||
"$PYBIN/pip" install virtualenv
|
||||
venv_dir=`mktemp -d`/venv
|
||||
"$PYBIN/python" -m virtualenv "$venv_dir"
|
||||
|
||||
# run the tests in a subshell to keep that `activate`
|
||||
# script from polluting the env
|
||||
(
|
||||
source "$venv_dir/bin/activate"
|
||||
|
||||
echo "Running tests using `which python`"
|
||||
|
||||
# Install the wheel we just built
|
||||
# Note: If auditwheel produced two wheels, it's because the earlier produced wheel
|
||||
# conforms to multiple manylinux standards. These multiple versions of the wheel are
|
||||
# functionally the same, differing only in name, wheel metadata, and possibly include
|
||||
# different external shared libraries. so it doesn't matter which one we run the tests on.
|
||||
# Let's just pick the first one.
|
||||
pip install "${{delocated_wheels[0]}}"{test_extras}
|
||||
|
||||
# Install any requirements to run the tests
|
||||
if [ ! -z "{test_requires}" ]; then
|
||||
pip install {test_requires}
|
||||
fi
|
||||
|
||||
# Run the tests from a different directory
|
||||
pushd $HOME
|
||||
sh -c {test_command}
|
||||
popd
|
||||
)
|
||||
# exit if tests failed (needed for older bash versions)
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# clean up
|
||||
rm -rf "$venv_dir"
|
||||
fi
|
||||
|
||||
# we're all done here; move it to output
|
||||
mv "$delocated_wheel" /output
|
||||
chown {uid}:{gid} "/output/$(basename "$delocated_wheel")"
|
||||
mv "${{delocated_wheels[@]}}" /output
|
||||
for delocated_wheel in "${{delocated_wheels[@]}}"; do chown {uid}:{gid} "/output/$(basename "$delocated_wheel")"; done
|
||||
done
|
||||
'''.format(
|
||||
pybin_paths=' '.join(c.path+'/bin' for c in platform_configs),
|
||||
test_requires=' '.join(test_requires),
|
||||
test_extras=test_extras,
|
||||
test_command=shlex_quote(
|
||||
prepare_command(test_command, project='/project') if test_command else ''
|
||||
),
|
||||
|
||||
+36
-13
@@ -1,4 +1,5 @@
|
||||
from __future__ import print_function
|
||||
import tempfile
|
||||
import os, subprocess, shlex, sys, shutil
|
||||
from collections import namedtuple
|
||||
from glob import glob
|
||||
@@ -13,18 +14,18 @@ from .util import prepare_command, get_build_verbosity_extra_flags
|
||||
def get_python_configurations(build_selector):
|
||||
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'identifier', 'url'])
|
||||
python_configurations = [
|
||||
PythonConfiguration(version='2.7', identifier='cp27-macosx_10_6_intel', url='https://www.python.org/ftp/python/2.7.16/python-2.7.16-macosx10.6.pkg'),
|
||||
PythonConfiguration(version='3.4', identifier='cp34-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.4.4/python-3.4.4-macosx10.6.pkg'),
|
||||
PythonConfiguration(version='2.7', identifier='cp27-macosx_10_6_intel', url='https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.6.pkg'),
|
||||
PythonConfiguration(version='3.5', identifier='cp35-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'),
|
||||
PythonConfiguration(version='3.6', identifier='cp36-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.6.pkg'),
|
||||
PythonConfiguration(version='3.7', identifier='cp37-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.7.2/python-3.7.2-macosx10.6.pkg'),
|
||||
PythonConfiguration(version='3.7', identifier='cp37-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.7.5/python-3.7.5-macosx10.6.pkg'),
|
||||
PythonConfiguration(version='3.8', identifier='cp38-macosx_10_9_x86_64', url='https://www.python.org/ftp/python/3.8.0/python-3.8.0-macosx10.9.pkg'),
|
||||
]
|
||||
|
||||
# skip builds as required
|
||||
return [c for c in python_configurations if build_selector(c.identifier)]
|
||||
|
||||
|
||||
def build(project_dir, output_dir, test_command, test_requires, before_build, build_verbosity, build_selector, environment):
|
||||
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment):
|
||||
python_configurations = get_python_configurations(build_selector)
|
||||
get_pip_url = 'https://bootstrap.pypa.io/get-pip.py'
|
||||
get_pip_script = '/tmp/get-pip.py'
|
||||
@@ -57,8 +58,8 @@ def build(project_dir, output_dir, test_command, test_requires, before_build, bu
|
||||
# install
|
||||
call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/'])
|
||||
# patch open ssl
|
||||
if config.version in ('3.4', '3.5'):
|
||||
call(['curl', '-fsSLo', '/tmp/python-patch.tar.gz', 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2r/patch-macos-python-%s-openssl-v1.0.2r.tar.gz' % config.version])
|
||||
if config.version == '3.5':
|
||||
call(['curl', '-fsSLo', '/tmp/python-patch.tar.gz', 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2t/patch-macos-python-%s-openssl-v1.0.2t.tar.gz' % config.version])
|
||||
call(['sudo', 'tar', '-C', '/Library/Frameworks/Python.framework/Versions/%s/' % config.version, '-xmf', '/tmp/python-patch.tar.gz'])
|
||||
|
||||
installation_bin_path = '/Library/Frameworks/Python.framework/Versions/{}/bin'.format(config.version)
|
||||
@@ -120,18 +121,40 @@ def build(project_dir, output_dir, test_command, test_requires, before_build, bu
|
||||
call(['delocate-wheel', '-w', '/tmp/delocated_wheel', built_wheel], env=env)
|
||||
delocated_wheel = glob('/tmp/delocated_wheel/*.whl')[0]
|
||||
|
||||
# install the wheel
|
||||
call(['pip', 'install', delocated_wheel], env=env)
|
||||
|
||||
# test the wheel
|
||||
if test_requires:
|
||||
call(['pip', 'install'] + test_requires, env=env)
|
||||
if test_command:
|
||||
# set up a virtual environment to install and test from, to make sure
|
||||
# there are no dependencies that were pulled in at build time.
|
||||
call(['pip', 'install', 'virtualenv'], env=env)
|
||||
venv_dir = tempfile.mkdtemp()
|
||||
call(['python', '-m', 'virtualenv', venv_dir], env=env)
|
||||
|
||||
virtualenv_env = env.copy()
|
||||
virtualenv_env['PATH'] = os.pathsep.join([
|
||||
os.path.join(venv_dir, 'bin'),
|
||||
virtualenv_env['PATH'],
|
||||
])
|
||||
# Fix some weird issue with the shebang of installed scripts
|
||||
# See https://github.com/theacodes/nox/issues/44 and https://github.com/pypa/virtualenv/issues/620
|
||||
virtualenv_env.pop('__PYVENV_LAUNCHER__', None)
|
||||
|
||||
# check that we are using the Python from the virtual environment
|
||||
call(['which', 'python'], env=virtualenv_env)
|
||||
|
||||
# install the wheel
|
||||
call(['pip', 'install', delocated_wheel + test_extras], env=virtualenv_env)
|
||||
|
||||
# test the wheel
|
||||
if test_requires:
|
||||
call(['pip', 'install'] + test_requires, env=virtualenv_env)
|
||||
|
||||
# run the tests from $HOME, with an absolute path in the command
|
||||
# (this ensures that Python runs the tests against the installed wheel
|
||||
# and not the repo code)
|
||||
test_command_prepared = prepare_command(test_command, project=abs_project_dir)
|
||||
call(test_command_prepared, cwd=os.environ['HOME'], env=env, shell=True)
|
||||
call(test_command_prepared, cwd=os.environ['HOME'], env=virtualenv_env, shell=True)
|
||||
|
||||
# clean up
|
||||
shutil.rmtree(venv_dir)
|
||||
|
||||
# we're all done here; move it to output (overwrite existing)
|
||||
dst = os.path.join(output_dir, os.path.basename(delocated_wheel))
|
||||
|
||||
+97
-56
@@ -1,72 +1,86 @@
|
||||
from __future__ import print_function
|
||||
import os, tempfile, subprocess, shutil
|
||||
import os, tempfile, subprocess, shutil, sys
|
||||
from collections import namedtuple
|
||||
from glob import glob
|
||||
|
||||
try:
|
||||
from shlex import quote as shlex_quote
|
||||
except ImportError:
|
||||
from pipes import quote as shlex_quote
|
||||
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
|
||||
from .util import prepare_command, get_build_verbosity_extra_flags
|
||||
|
||||
|
||||
IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
|
||||
IS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows'
|
||||
|
||||
|
||||
def get_python_path(config):
|
||||
if IS_RUNNING_ON_AZURE:
|
||||
# We can't hard-code the paths because on Azure, we don't know which
|
||||
# bugfix release of Python we are getting so we need to check which
|
||||
# ones exist. We just use the first one that is found since there should
|
||||
# only be one.
|
||||
path_pattern = 'C:\\hostedtoolcache\\windows\\Python\\{version}\\{arch}'.format(
|
||||
version=config.version.replace('x', '*'),
|
||||
arch='x86' if config.arch == '32' else 'x64'
|
||||
)
|
||||
try:
|
||||
return glob(path_pattern)[0]
|
||||
except IndexError:
|
||||
raise Exception('Could not find a Python install at ' + path_pattern)
|
||||
else:
|
||||
# Assume we're running on Appveyor
|
||||
major, minor = config.version.split('.')[:2]
|
||||
return 'C:\\Python{major}{minor}{arch}'.format(
|
||||
major=major,
|
||||
minor=minor,
|
||||
arch = '-x64' if config.arch == '64' else ''
|
||||
)
|
||||
nuget_args = get_nuget_args(config)
|
||||
return os.path.join(nuget_args[-1], nuget_args[0] + "." + config.version, "tools")
|
||||
|
||||
|
||||
def get_nuget_args(configuration):
|
||||
python_name = "python" if configuration.version[0] == '3' else "python2"
|
||||
if configuration.arch == "32":
|
||||
python_name = python_name + "x86"
|
||||
return [python_name, "-Version", configuration.version, "-OutputDirectory", "C:/cibw/python"]
|
||||
|
||||
def get_python_configurations(build_selector):
|
||||
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier', 'path'])
|
||||
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier'])
|
||||
python_configurations = [
|
||||
PythonConfiguration(version='2.7.x', arch="32", identifier='cp27-win32', path='C:\Python27'),
|
||||
PythonConfiguration(version='2.7.x', arch="64", identifier='cp27-win_amd64', path='C:\Python27-x64'),
|
||||
PythonConfiguration(version='3.4.x', arch="32", identifier='cp34-win32', path='C:\Python34'),
|
||||
PythonConfiguration(version='3.4.x', arch="64", identifier='cp34-win_amd64', path='C:\Python34-x64'),
|
||||
PythonConfiguration(version='3.5.x', arch="32", identifier='cp35-win32', path='C:\Python35'),
|
||||
PythonConfiguration(version='3.5.x', arch="64", identifier='cp35-win_amd64', path='C:\Python35-x64'),
|
||||
PythonConfiguration(version='3.6.x', arch="32", identifier='cp36-win32', path='C:\Python36'),
|
||||
PythonConfiguration(version='3.6.x', arch="64", identifier='cp36-win_amd64', path='C:\Python36-x64'),
|
||||
PythonConfiguration(version='3.7.x', arch="32", identifier='cp37-win32', path='C:\Python37'),
|
||||
PythonConfiguration(version='3.7.x', arch="64", identifier='cp37-win_amd64', path='C:\Python37-x64'),
|
||||
PythonConfiguration(version='2.7.17', arch="32", identifier='cp27-win32'),
|
||||
PythonConfiguration(version='2.7.17', arch="64", identifier='cp27-win_amd64'),
|
||||
PythonConfiguration(version='3.5.4', arch="32", identifier='cp35-win32'),
|
||||
PythonConfiguration(version='3.5.4', arch="64", identifier='cp35-win_amd64'),
|
||||
PythonConfiguration(version='3.6.8', arch="32", identifier='cp36-win32'),
|
||||
PythonConfiguration(version='3.6.8', arch="64", identifier='cp36-win_amd64'),
|
||||
PythonConfiguration(version='3.7.5', arch="32", identifier='cp37-win32'),
|
||||
PythonConfiguration(version='3.7.5', arch="64", identifier='cp37-win_amd64'),
|
||||
PythonConfiguration(version='3.8.0', arch="32", identifier='cp38-win32'),
|
||||
PythonConfiguration(version='3.8.0', arch="64", identifier='cp38-win_amd64'),
|
||||
]
|
||||
|
||||
if IS_RUNNING_ON_AZURE:
|
||||
# Python 3.4 isn't supported on Azure.
|
||||
# See https://github.com/Microsoft/azure-pipelines-tasks/issues/9674
|
||||
python_configurations = [c for c in python_configurations if c.version != '3.4.x']
|
||||
if IS_RUNNING_ON_TRAVIS:
|
||||
# cannot install VCForPython27.msi which is needed for compiling C software
|
||||
# try with (and similar): msiexec /i VCForPython27.msi ALLUSERS=1 ACCEPT=YES /passive
|
||||
python_configurations = [c for c in python_configurations if not c.version.startswith('2.7.')]
|
||||
|
||||
# skip builds as required
|
||||
return [c for c in python_configurations if build_selector(c.identifier)]
|
||||
# skip builds as required
|
||||
python_configurations = [c for c in python_configurations if build_selector(c.identifier)]
|
||||
|
||||
return python_configurations
|
||||
|
||||
|
||||
def build(project_dir, output_dir, test_command, test_requires, before_build, build_verbosity, build_selector, environment):
|
||||
if IS_RUNNING_ON_AZURE:
|
||||
def shell(args, env=None, cwd=None):
|
||||
print('+ ' + ' '.join(args))
|
||||
args = ['cmd', '/E:ON', '/V:ON', '/C'] + args
|
||||
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
|
||||
|
||||
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment):
|
||||
def simple_shell(args, env=None, cwd=None):
|
||||
print('+ ' + ' '.join(args))
|
||||
args = ['cmd', '/E:ON', '/V:ON', '/C'] + args
|
||||
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
|
||||
def download(url, dest):
|
||||
print('+ Download ' + url + ' to ' + dest)
|
||||
dest_dir = os.path.dirname(dest)
|
||||
if not os.path.exists(dest_dir):
|
||||
os.makedirs(dest_dir)
|
||||
response = urlopen(url)
|
||||
try:
|
||||
with open(dest, 'wb') as file:
|
||||
file.write(response.read())
|
||||
finally:
|
||||
response.close()
|
||||
if IS_RUNNING_ON_AZURE or IS_RUNNING_ON_TRAVIS:
|
||||
shell = simple_shell
|
||||
else:
|
||||
run_with_env = os.path.abspath(os.path.join(os.path.dirname(__file__), 'resources', 'appveyor_run_with_env.cmd'))
|
||||
|
||||
# run_with_env is a cmd file that sets the right environment variables
|
||||
# to build on Appveyor.
|
||||
# to build on AppVeyor.
|
||||
def shell(args, env=None, cwd=None):
|
||||
# print the command executing for the logs
|
||||
print('+ ' + ' '.join(args))
|
||||
@@ -77,10 +91,19 @@ def build(project_dir, output_dir, test_command, test_requires, before_build, bu
|
||||
temp_dir = tempfile.mkdtemp(prefix='cibuildwheel')
|
||||
built_wheel_dir = os.path.join(temp_dir, 'built_wheel')
|
||||
|
||||
python_configurations = get_python_configurations(build_selector)
|
||||
# install nuget as best way to provide python
|
||||
nuget = 'C:\\cibw\\nuget.exe'
|
||||
download('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', nuget)
|
||||
# get pip fo this installation which not have.
|
||||
get_pip_script = 'C:\\cibw\\get-pip.py'
|
||||
download('https://bootstrap.pypa.io/get-pip.py', get_pip_script)
|
||||
|
||||
python_configurations = get_python_configurations(build_selector)
|
||||
for config in python_configurations:
|
||||
config_python_path = get_python_path(config)
|
||||
simple_shell([nuget, "install"] + get_nuget_args(config))
|
||||
if not os.path.exists(os.path.join(config_python_path, 'Scripts', 'pip.exe')):
|
||||
simple_shell([os.path.join(config_python_path, 'python.exe'), get_pip_script ])
|
||||
|
||||
# check python & pip exist for this configuration
|
||||
assert os.path.exists(os.path.join(config_python_path, 'python.exe'))
|
||||
@@ -107,8 +130,7 @@ def build(project_dir, output_dir, test_command, test_requires, before_build, bu
|
||||
shell(['python', '-c', '"import struct; print(struct.calcsize(\'P\') * 8)\"'], env=env)
|
||||
|
||||
# prepare the Python environment
|
||||
shell(['python', '-m', 'pip', 'install', '--upgrade', 'pip'],
|
||||
env=env)
|
||||
shell(['python', '-m', 'pip', 'install', '--upgrade', 'pip'], env=env)
|
||||
shell(['pip', 'install', '--upgrade', 'setuptools'], env=env)
|
||||
shell(['pip', 'install', 'wheel'], env=env)
|
||||
|
||||
@@ -121,18 +143,37 @@ def build(project_dir, output_dir, test_command, test_requires, before_build, bu
|
||||
shell(['pip', 'wheel', abs_project_dir, '-w', built_wheel_dir, '--no-deps'] + get_build_verbosity_extra_flags(build_verbosity), env=env)
|
||||
built_wheel = glob(built_wheel_dir+'/*.whl')[0]
|
||||
|
||||
# install the wheel
|
||||
shell(['pip', 'install', built_wheel], env=env)
|
||||
|
||||
# test the wheel
|
||||
if test_requires:
|
||||
shell(['pip', 'install'] + test_requires, env=env)
|
||||
if test_command:
|
||||
# set up a virtual environment to install and test from, to make sure
|
||||
# there are no dependencies that were pulled in at build time.
|
||||
shell(['pip', 'install', 'virtualenv'], env=env)
|
||||
venv_dir = tempfile.mkdtemp()
|
||||
shell(['python', '-m', 'virtualenv', venv_dir], env=env)
|
||||
|
||||
virtualenv_env = env.copy()
|
||||
virtualenv_env['PATH'] = os.pathsep.join([
|
||||
os.path.join(venv_dir, 'Scripts'),
|
||||
virtualenv_env['PATH'],
|
||||
])
|
||||
|
||||
# check that we are using the Python from the virtual environment
|
||||
shell(['which', 'python'], env=virtualenv_env)
|
||||
|
||||
# install the wheel
|
||||
shell(['pip', 'install', built_wheel + test_extras], env=virtualenv_env)
|
||||
|
||||
# test the wheel
|
||||
if test_requires:
|
||||
shell(['pip', 'install'] + test_requires, env=virtualenv_env)
|
||||
|
||||
# run the tests from c:\, with an absolute path in the command
|
||||
# (this ensures that Python runs the tests against the installed wheel
|
||||
# and not the repo code)
|
||||
test_command_prepared = prepare_command(test_command, project=abs_project_dir)
|
||||
shell([test_command_prepared], cwd='c:\\', env=env)
|
||||
shell([test_command_prepared], cwd='c:\\', env=virtualenv_env)
|
||||
|
||||
# clean up
|
||||
shutil.rmtree(venv_dir)
|
||||
|
||||
# we're all done here; move it to output (remove if already exists)
|
||||
dst = os.path.join(output_dir, os.path.basename(built_wheel))
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: Contributing
|
||||
---
|
||||
|
||||
Wheel-building can be pretty complex. I expect users to find many edge-cases - please help the rest of the community out by documenting these, adding features to support them, and reporting bugs.
|
||||
|
||||
I plan to be pretty liberal in accepting pull requests, as long as they align with the design goals below.
|
||||
|
||||
`cibuildwheel` is indie open source. We're not paid to work on this.
|
||||
|
||||
Design Goals
|
||||
------------
|
||||
|
||||
- `cibuildwheel` should wrap the complexity of wheel building.
|
||||
- The user interface to `cibuildwheel` is the build script (e.g. `.travis.yml`). Feature additions should not increase the complexity of this script.
|
||||
- Options should be environment variables (these lend themselves better to YML config files). They should be prefixed with `CIBW_`.
|
||||
- Options should be generalise to all platforms. If platform-specific options are required, they should be namespaced e.g. `CIBW_TEST_COMMAND_MACOS`
|
||||
|
||||
Other notes:
|
||||
|
||||
- The platforms are very similar, until they're not. I'd rather have straight-forward code than totally DRY code, so let's keep airy platfrom abstractions to a minimum.
|
||||
- I might want to break the options into a shared config file one day, so that config is more easily shared. That has motivated some of the design decisions.
|
||||
|
||||
### cibuildwheel's relationship with build errors
|
||||
|
||||
cibuildwheel doesn't really do anything itself - it's always deferring to other tools (pip, wheel, auditwheel, delocate, docker). Without cibuildwheel, the process is really fragmented. Different tools, across different OSs need to be stitched together in just the right way to make it work.
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Delivering to PyPI
|
||||
---
|
||||
|
||||
After you've built your wheels, you'll probably want to deliver them to PyPI.
|
||||
|
||||
### Manual method
|
||||
|
||||
On your development machine, do the following...
|
||||
|
||||
```bash
|
||||
# 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
|
||||
# 'dist' folder.
|
||||
|
||||
# Upload using 'twine' (you may need to 'pip install twine')
|
||||
twine upload dist/*
|
||||
```
|
||||
|
||||
### Semi-automatic method using wheelhouse-uploader
|
||||
|
||||
Obviously, manual steps are for chumps, so we can automate this a little by using [wheelhouse-uploader](https://github.com/ogrisel/wheelhouse-uploader).
|
||||
|
||||
> Quick note from me - using S3 as a storage didn't work due to a [bug](https://issues.apache.org/jira/browse/LIBCLOUD-792) in libcloud. Feel free to use my fork of that package that fixes the bug `pip install https://github.com/joerick/libcloud/archive/v1.5.0-s3fix.zip`
|
||||
|
||||
### Automatic method
|
||||
|
||||
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.
|
||||
|
||||
Check out [this example repo](https://github.com/joerick/cibuildwheel-autopypi-example) for instructions on how to set this up.
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
/* Global styles */
|
||||
|
||||
p {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 85%;
|
||||
background-color: rgba(27,31,35,.05);
|
||||
border-radius: 3px;
|
||||
padding: .2em .4em;
|
||||
color: inherit;
|
||||
border: none;
|
||||
margin: 0 1px;
|
||||
}
|
||||
|
||||
code, pre, tt {
|
||||
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
|
||||
}
|
||||
|
||||
.hljs {
|
||||
padding: 1em;
|
||||
background-color: #f6f8fa;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 2em;
|
||||
border-bottom: 1px solid #e1e4e5;
|
||||
margin-bottom: 0.8em;
|
||||
padding-bottom: 0.2em;
|
||||
|
||||
}
|
||||
|
||||
.rst-content blockquote {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.rst-content th {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/*
|
||||
Code block filename style
|
||||
|
||||
Use by putting a quote before a code block e.g.
|
||||
|
||||
> filename.txt
|
||||
|
||||
```
|
||||
code here
|
||||
```
|
||||
|
||||
JS adds the relevant classes to make the following selectors work.
|
||||
*/
|
||||
.rst-content .code-block-filename {
|
||||
margin: 0;
|
||||
padding: 2px 1em;
|
||||
background-color: #eff1f3;
|
||||
font-size: 85%;
|
||||
font-weight: bold;
|
||||
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
|
||||
border-bottom: 1px solid #e6e8e9;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.rst-content .code-block-filename * {
|
||||
font-size: inherit;
|
||||
}
|
||||
.rst-content .code-block-filename :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.code-block-filename + pre {
|
||||
margin-top: 0;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.code-block-filename + pre code {
|
||||
padding-top: 0.9em;
|
||||
}
|
||||
|
||||
/* import font awesome 4 for icons */
|
||||
@import url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css);
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
$('.rst-content pre')
|
||||
.prev('blockquote')
|
||||
.addClass('code-block-filename');
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: Tips and tricks
|
||||
---
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If your wheel didn't compile, check the list below for some debugging tips.
|
||||
|
||||
- A mistake in your config. To quickly test your config without doing a git push and waiting for your code to build on CI, you can test the Linux build in a Docker container. On Mac or Linux, with Docker running, try `cibuildwheel --platform linux`. You'll have to bring your config into the current environment first.
|
||||
|
||||
- Missing dependency. You might need to install something on the build machine. You can do this in `.travis.yml`, `appveyor.yml`, or `.circleci/config.yml`, with apt-get, brew or choco. Given how the Linux build works, you'll need to use the [`CIBW_BEFORE_BUILD`](options.md#before-build) option.
|
||||
|
||||
- Windows: missing C feature. The Windows C compiler doesn't support C language features invented after 1990, so you'll have to backport your C code to C90. For me, this mostly involved putting my variable declarations at the top of the function like an animal.
|
||||
|
||||
- MacOS: calling cibuildwheel from a python3 script and getting a `ModuleNotFoundError`? Due to a [bug](https://bugs.python.org/issue22490) in CPython, you'll need to [unset the `__PYVENV_LAUNCHER__` variable](https://github.com/joerick/cibuildwheel/issues/133#issuecomment-478288597) before activating a venv.
|
||||
|
||||
### Linux builds on Docker
|
||||
|
||||
Linux wheels are built in the [`manylinux` docker images](https://github.com/pypa/manylinux) to provide binary compatible wheels on Linux, according to [PEP 571](https://www.python.org/dev/peps/pep-0571/). Because of this, when building with `cibuildwheel` on Linux, a few things should be taken into account:
|
||||
|
||||
- Programs and libraries cannot be installed on the Travis CI Ubuntu host with `apt-get`, but can be installed inside of the Docker image using `yum` or manually. The same goes for environment variables that are potentially needed to customize the wheel building. `cibuildwheel` supports this by providing the `CIBW_ENVIRONMENT` and `CIBW_BEFORE_BUILD` options to setup the build environment inside the running Docker image. See [the options docs](options.md#build-environment) for details on these options.
|
||||
|
||||
- The project directory is mounted in the running Docker instance as `/project`, the output directory for the wheels as `/output`. In general, this is handled transparently by `cibuildwheel`. For a more finegrained level of control however, the root of the host file system is mounted as `/host`, allowing for example to access shared files, caches, etc. on the host file system. Note that this is not available on CircleCI due to their Docker policies.
|
||||
|
||||
- Alternative dockers images can be specified with the `CIBW_MANYLINUX_X86_64_IMAGE` and `CIBW_MANYLINUX_I686_IMAGE` options to allow for a custom, preconfigured build environment for the Linux builds. See [options](options.md#manylinux-image) for more details.
|
||||
|
||||
### Building packages with optional C extensions
|
||||
|
||||
`cibuildwheel` defines the environment variable `CIBUILDWHEEL` to the value `1` allowing projects for which the C extension is optional to make it mandatory when building wheels.
|
||||
|
||||
An easy way to do it in Python 3 is through the `optional` named argument of `Extension` constructor in your `setup.py`:
|
||||
|
||||
```python
|
||||
myextension = Extension(
|
||||
"myextension",
|
||||
["myextension.c"],
|
||||
optional=os.environ.get('CIBUILDWHEEL', '0') != '1',
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: Home
|
||||
---
|
||||
|
||||
{%
|
||||
includemarkdown "../README.md"
|
||||
start="<!--intro-start-->"
|
||||
end="<!--intro-end-->"
|
||||
%}
|
||||
|
||||
To get started, head over to the [setup guide](setup.md).
|
||||
@@ -0,0 +1,51 @@
|
||||
import mkdocs, re, os, io, cgi
|
||||
|
||||
TAG_REGEX_PATTERN = re.compile(
|
||||
r'''
|
||||
{% # opening tag
|
||||
\s*
|
||||
includemarkdown # directive name
|
||||
\s+
|
||||
"(?P<filename>[^"]+)" # "filename"
|
||||
(?:\s+start="(?P<start>[^"]+)")? # optional start expression
|
||||
(?:\s+end="(?P<end>[^"]+)")? # optional end expression
|
||||
\s*
|
||||
%} # closing tag
|
||||
''',
|
||||
flags=re.VERBOSE,
|
||||
)
|
||||
|
||||
class ImportMarkdownPlugin(mkdocs.plugins.BasePlugin):
|
||||
def on_page_markdown(self, markdown, page, **kwargs):
|
||||
page_src_path = page.file.abs_src_path
|
||||
|
||||
def found_import_markdown_tag(match):
|
||||
filename = match.group('filename')
|
||||
start = match.group('start')
|
||||
end = match.group('end')
|
||||
|
||||
file_path_abs = os.path.join(os.path.dirname(page_src_path), filename)
|
||||
|
||||
if not os.path.exists(file_path_abs):
|
||||
raise ValueError('file not found', filename)
|
||||
|
||||
with io.open(file_path_abs, encoding='utf8') as f:
|
||||
text_to_include = f.read()
|
||||
|
||||
if start:
|
||||
_, _, text_to_include = text_to_include.partition(start)
|
||||
|
||||
if end:
|
||||
text_to_include, _, _ = text_to_include.partition(end)
|
||||
|
||||
return (
|
||||
'<!-- BEGIN INCLUDE %s %s %s -->' % (
|
||||
filename, cgi.escape(start), cgi.escape(end)
|
||||
)
|
||||
+ text_to_include
|
||||
+ '<!-- END INCLUDE -->'
|
||||
)
|
||||
|
||||
markdown = re.sub(TAG_REGEX_PATTERN, found_import_markdown_tag, markdown)
|
||||
return markdown
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='mkdocs_include_markdown_plugin',
|
||||
version='1.0',
|
||||
author='Joe Rickerby',
|
||||
license='Apache 2',
|
||||
packages=['mkdocs_include_markdown_plugin'],
|
||||
entry_points={
|
||||
'mkdocs.plugins': [
|
||||
'importmarkdown = mkdocs_include_markdown_plugin.plugin:ImportMarkdownPlugin',
|
||||
]
|
||||
},
|
||||
zip_safe=False
|
||||
)
|
||||
+451
@@ -0,0 +1,451 @@
|
||||
## Options summary
|
||||
|
||||
<div class="options-toc"></div>
|
||||
|
||||
## Setting options
|
||||
|
||||
cibuildwheel is configured using environment variables, that can be set using
|
||||
your CI config.
|
||||
|
||||
For example, to configure cibuildwheel to run tests, add the following YAML to
|
||||
your CI config file:
|
||||
|
||||
> .travis.yml ([docs](https://docs.travis-ci.com/user/environment-variables/))
|
||||
```yaml
|
||||
env:
|
||||
global:
|
||||
- CIBW_TEST_REQUIRES=nose
|
||||
- CIBW_TEST_COMMAND="nosetests {project}/tests"
|
||||
```
|
||||
|
||||
> appveyor.yml ([docs](https://www.appveyor.com/docs/build-configuration/#environment-variables))
|
||||
```yaml
|
||||
environment:
|
||||
global:
|
||||
CIBW_TEST_REQUIRES: nose
|
||||
CIBW_TEST_COMMAND: "nosetests {project}\\tests"
|
||||
```
|
||||
|
||||
> .circleci/config.yml ([docs](https://circleci.com/docs/2.0/configuration-reference/#environment))
|
||||
```yaml
|
||||
jobs:
|
||||
job_name:
|
||||
environment:
|
||||
CIBW_TEST_REQUIRES: nose
|
||||
CIBW_TEST_COMMAND: "nosetests {project}/tests"
|
||||
```
|
||||
|
||||
> azure-pipelines.yml ([docs](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables))
|
||||
```yaml
|
||||
variables:
|
||||
CIBW_TEST_REQUIRES: nose
|
||||
CIBW_TEST_COMMAND: "nosetests {project}/tests"
|
||||
```
|
||||
|
||||
|
||||
## Build selection
|
||||
|
||||
|
||||
### `CIBW_PLATFORM` {: #platform}
|
||||
|
||||
> Override the auto-detected target platform
|
||||
|
||||
Options: `auto` `linux` `macos` `windows`
|
||||
|
||||
Default: `auto`
|
||||
|
||||
`auto` will auto-detect platform using environment variables, such as `TRAVIS_OS_NAME`/`APPVEYOR`/`CIRCLECI`.
|
||||
|
||||
For `linux` you need Docker running, on Mac or Linux. For `macos`, you need a Mac machine, and note that this script is going to automatically install MacPython on your system, so don't run on your development machine. For `windows`, you need to run in Windows, and it will build and test for all versions of Python at `C:\PythonXX[-x64]`.
|
||||
|
||||
This option can also be set using the command-line option `--platform`.
|
||||
|
||||
### `CIBW_BUILD`, `CIBW_SKIP` {: #build-skip}
|
||||
|
||||
> Choose the Python versions to build
|
||||
|
||||
Space-separated list of builds to build and skip. Each build has an identifier like `cp27-manylinux_x86_64` or `cp35-macosx_10_6_intel` - you can list specific ones to build and `cibuildwheel` will only build those, and/or list ones to skip and `cibuildwheel` won't try to build them.
|
||||
|
||||
When both options are specified, both conditions are applied and only builds with a tag that matches `CIBW_BUILD` and does not match `CIBW_SKIP` will be built.
|
||||
|
||||
When setting the options, you can use shell-style globbing syntax (as per `fnmatch`). All the build identifiers supported by cibuildwheel are shown below:
|
||||
|
||||
<div class="build-id-table-marker"></div>
|
||||
|
||||
| | macOS 64bit | macOS 32/64bit | Manylinux 64bit | Manylinux 32bit | Windows 64bit | Windows 32bit |
|
||||
|------------|-------------------------|------------------------|------------------------|----------------------|-----------------|----------------|
|
||||
| Python 2.7 | | cp27-macosx_10_6_intel | cp27-manylinux_x86_64 | cp27-manylinux_i686 | cp27-win_amd64 | cp27-win32 |
|
||||
| Python 3.5 | | cp35-macosx_10_6_intel | cp35-manylinux_x86_64 | cp35-manylinux_i686 | cp35-win_amd64 | cp35-win32 |
|
||||
| Python 3.6 | | cp36-macosx_10_6_intel | cp36-manylinux_x86_64 | cp36-manylinux_i686 | cp36-win_amd64 | cp36-win32 |
|
||||
| Python 3.7 | | cp37-macosx_10_6_intel | cp37-manylinux_x86_64 | cp37-manylinux_i686 | cp37-win_amd64 | cp37-win32 |
|
||||
| Python 3.8 | cp38-macosx_10_9_x86_64 | | cp38-manylinux_x86_64 | cp38-manylinux_i686 | cp38-win_amd64 | cp38-win32 |
|
||||
|
||||
The list of supported and currently selected build identifiers can also be retrieved by passing the `--print-build-identifiers` flag to `cibuildwheel`.
|
||||
The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details).
|
||||
|
||||
#### Examples
|
||||
|
||||
```yaml
|
||||
# Only build on Python 3.6
|
||||
CIBW_BUILD: cp36-*
|
||||
|
||||
# Skip building on Python 2.7 on the Mac
|
||||
CIBW_SKIP: cp27-macosx_10_6_intel
|
||||
|
||||
# Skip building on Python 3.8 on the Mac
|
||||
CIBW_SKIP: cp38-macosx_10_9_x86_64
|
||||
|
||||
# Skip building on Python 2.7 on all platforms
|
||||
CIBW_SKIP: cp27-*
|
||||
|
||||
# Skip Python 2.7 on Windows
|
||||
CIBW_SKIP: cp27-win*
|
||||
|
||||
# Skip Python 2.7 on 32-bit Windows
|
||||
CIBW_SKIP: cp27-win32
|
||||
|
||||
# Skip Python 2.7 and Python 3.5
|
||||
CIBW_SKIP: cp27-* cp35-*
|
||||
|
||||
# Skip Python 3.6 on Linux
|
||||
CIBW_SKIP: cp36-manylinux*
|
||||
|
||||
# Only build on Python 3 and skip 32-bit builds
|
||||
CIBW_BUILD: cp3?-*
|
||||
CIBW_SKIP: "*-win32 *-manylinux_i686"
|
||||
```
|
||||
|
||||
<style>
|
||||
.build-id-table-marker + table {
|
||||
font-size: 90%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.rst-content .build-id-table-marker + table td,
|
||||
.rst-content .build-id-table-marker + table th {
|
||||
padding: 4px 4px;
|
||||
}
|
||||
.build-id-table-marker + table td:not(:first-child) {
|
||||
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
|
||||
font-size: 85%;
|
||||
}
|
||||
dt code {
|
||||
font-size: 100%;
|
||||
background-color: rgba(41, 128, 185, 0.1);
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
## Build customization
|
||||
|
||||
|
||||
### `CIBW_ENVIRONMENT` {: #environment}
|
||||
> Set environment variables needed during the build
|
||||
|
||||
A space-separated list of environment variables to set during the build. Bash syntax should be used, even on Windows.
|
||||
|
||||
You must set this variable to pass variables to Linux builds (since they execute in a Docker container). It also works for the other platforms.
|
||||
|
||||
You can use `$PATH` syntax to insert other variables, or the `$(pwd)` syntax to insert the output of other shell commands.
|
||||
|
||||
#### Examples
|
||||
```yaml
|
||||
# Set some compiler flags
|
||||
CIBW_ENVIRONMENT: "CFLAGS='-g -Wall' CXXFLAGS='-Wall'"
|
||||
|
||||
# Append a directory to the PATH variable (this is expanded in the build environment)
|
||||
CIBW_ENVIRONMENT: "PATH=$PATH:/usr/local/bin"
|
||||
|
||||
# Set BUILD_TIME to the output of the `date` command
|
||||
CIBW_ENVIRONMENT: "BUILD_TIME=$(date)"
|
||||
|
||||
# Supply options to `pip` to affect how it downloads dependencies
|
||||
CIBW_ENVIRONMENT: "PIP_EXTRA_INDEX_URL=https://pypi.myorg.com/simple"
|
||||
```
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_ENVIRONMENT_MACOS` | `CIBW_ENVIRONMENT_WINDOWS` | `CIBW_ENVIRONMENT_LINUX`
|
||||
|
||||
!!! note
|
||||
`cibuildwheel` always defines the environment variable `CIBUILDWHEEL=1`. This can be useful for [building wheels with optional extensions](faq.md#building-packages-with-optional-c-extensions).
|
||||
|
||||
|
||||
### `CIBW_BEFORE_BUILD` {: #before-build}
|
||||
> Execute a shell command preparing each wheel's build
|
||||
|
||||
A shell command to run before building the wheel. This option allows you to run a command in **each** Python environment before the `pip wheel` command. This is useful if you need to set up some dependency so it's available during the build.
|
||||
|
||||
If dependencies are required to build your wheel (for example if you include a header from a Python module), set this to `pip install .`, and the dependencies will be installed automatically by pip. However, this means your package will be built twice - if your package takes a long time to build, you might wish to manually list the dependencies here instead.
|
||||
|
||||
The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root.
|
||||
|
||||
#### Examples
|
||||
```yaml
|
||||
# install your project and dependencies before building
|
||||
CIBW_BEFORE_BUILD: pip install .
|
||||
|
||||
# install something required for the build
|
||||
CIBW_BEFORE_BUILD: pip install pybind11
|
||||
|
||||
# chain commands using &&
|
||||
CIBW_BEFORE_BUILD: yum install -y libffi-dev && pip install .
|
||||
```
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_BEFORE_BUILD_MACOS` | `CIBW_BEFORE_BUILD_WINDOWS` | `CIBW_BEFORE_BUILD_LINUX`
|
||||
|
||||
|
||||
### `CIBW_MANYLINUX_X86_64_IMAGE`, `CIBW_MANYLINUX_I686_IMAGE` {: #manylinux-image}
|
||||
> Specify alternative manylinux docker images
|
||||
|
||||
An alternative Docker image to be used for building [`manylinux`](https://github.com/pypa/manylinux) wheels. `cibuildwheel` will then pull these instead of the default images, [`quay.io/pypa/manylinux2010_x86_64`](https://quay.io/pypa/manylinux2010_x86_64) and [`quay.io/pypa/manylinux2010_i686`](https://quay.io/pypa/manylinux2010_i686).
|
||||
|
||||
The value of this option can either be set to `manylinux1` or `manylinux2010` to use the [official `manylinux` images](https://github.com/pypa/manylinux), or any other valid Docker image name.
|
||||
|
||||
Beware to specify a valid Docker image that can be used in the same way as the official, default Docker images: all necessary Python and pip versions need to be present in `/opt/python/`, and the `auditwheel` tool needs to be present for `cibuildwheel` to work. Apart from that, the architecture and relevant shared system libraries need to be manylinux1- or manylinux2010-compatible in order to produce valid `manylinux1`/`manylinux2010` wheels (see https://github.com/pypa/manylinux, [PEP 513](https://www.python.org/dev/peps/pep-0513/), and [PEP 571](https://www.python.org/dev/peps/pep-0571/) for more details).
|
||||
|
||||
Note that `auditwheel` detects the version of the `manylinux` standard in the Docker image through the `AUDITWHEEL_PLAT` environment variable, as `cibuildwheel` has no way of detecting the correct `--plat` command line argument to pass to `auditwheel` for a custom image. If a Docker image does not correctly set this `AUDITWHEEL_PLAT` environment variable, the `CIBW_ENVIRONMENT` option can be used to do so (e.g., `CIBW_ENVIRONMENT="manylinux2010_$(uname -m)"`).
|
||||
|
||||
#### Examples
|
||||
|
||||
```yaml
|
||||
# build using the manylinux1 image to ensure manylinux1 wheels are produced
|
||||
CIBW_MANYLINUX_X86_64_IMAGE: manylinux1
|
||||
CIBW_MANYLINUX_I686_IMAGE: manylinux1
|
||||
|
||||
# build using a different image from the docker registry
|
||||
CIBW_MANYLINUX_X86_64_IMAGE: dockcross/manylinux-x64
|
||||
CIBW_MANYLINUX_I686_IMAGE: dockcross/manylinux-x86
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### `CIBW_TEST_COMMAND` {: #test-command}
|
||||
> Execute a shell command to test all built wheels
|
||||
|
||||
Shell command to run tests after the build. The wheel will be installed automatically and available for import from the tests. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`.
|
||||
|
||||
On Linux and Mac, the command runs in a shell, so you can write things like `cmd1 && cmd2`.
|
||||
|
||||
#### Examples
|
||||
|
||||
```yaml
|
||||
# run the project tests against the installed wheel using `nose`
|
||||
CIBW_TEST_COMMAND: nosetests {project}/tests
|
||||
|
||||
# run the project tests using `pytest`
|
||||
CIBW_TEST_COMMAND: nosetests {project}/tests
|
||||
```
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_TEST_COMMAND_MACOS` | `CIBW_TEST_COMMAND_WINDOWS` | `CIBW_TEST_COMMAND_LINUX`
|
||||
|
||||
|
||||
### `CIBW_TEST_REQUIRES` {: #test-requires}
|
||||
> Install Python dependencies before running the tests
|
||||
|
||||
Space-separated list of dependencies required for running the tests.
|
||||
|
||||
#### Examples
|
||||
|
||||
```yaml
|
||||
# install pytest before running CIBW_TEST_COMMAND
|
||||
CIBW_TEST_REQUIRES: pytest
|
||||
|
||||
# install specific versions of test dependencies
|
||||
CIBW_TEST_REQUIRES: nose==1.3.7 moto==0.4.31
|
||||
```
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_TEST_REQUIRES_MACOS` | `CIBW_TEST_REQUIRES_WINDOWS` | `CIBW_TEST_REQUIRES_LINUX`
|
||||
|
||||
### `CIBW_TEST_EXTRAS` {: #test-extras}
|
||||
> Install your wheel for testing using `extras_require`
|
||||
|
||||
Comma-separated list of
|
||||
[extras_require](https://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies)
|
||||
options that should be included when installing the wheel prior to running the
|
||||
tests. This can be used to avoid having to redefine test dependencies in
|
||||
`CIBW_TEST_REQUIRES` if they are already defined in `setup.py` or
|
||||
`setup.cfg`.
|
||||
|
||||
#### Examples
|
||||
|
||||
```yaml
|
||||
# will cause the wheel to be installed with `pip install <wheel_file>[test,qt]`
|
||||
CIBW_TEST_EXTRAS: test,qt
|
||||
```
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_TEST_EXTRAS_MACOS` | `CIBW_TEST_EXTRAS_WINDOWS` | `CIBW_TEST_EXTRAS_LINUX`
|
||||
|
||||
## Other
|
||||
|
||||
### `CIBW_BUILD_VERBOSITY` {: #build-verbosity}
|
||||
> Increase/decrease the output of pip wheel
|
||||
|
||||
An number from 1 to 3 to increase the level of verbosity (corresponding to invoking pip with `-v`, `-vv`, and `-vvv`), between -1 and -3 (`-q`, `-qq`, and `-qqq`), or just 0 (default verbosity). These flags are useful while debugging a build when the output of the actual build invoked by `pip wheel` is required.
|
||||
|
||||
#### Examples
|
||||
|
||||
```yaml
|
||||
# increase pip debugging output
|
||||
CIBW_BUILD_VERBOSITY: 1
|
||||
```
|
||||
|
||||
Platform-specific variants also available:
|
||||
`CIBW_BUILD_VERBOSITY_MACOS` | `CIBW_BUILD_VERBOSITY_WINDOWS` | `CIBW_BUILD_VERBOSITY_LINUX`
|
||||
|
||||
## Command line options
|
||||
|
||||
```text
|
||||
usage: cibuildwheel [-h] [--platform {auto,linux,macos,windows}]
|
||||
[--output-dir OUTPUT_DIR] [--print-build-identifiers]
|
||||
[project_dir]
|
||||
|
||||
Build wheels for all the platforms.
|
||||
|
||||
positional arguments:
|
||||
project_dir Path to the project that you want wheels for.
|
||||
Default: the current directory.
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--platform {auto,linux,macos,windows}
|
||||
Platform to build for. For "linux" you need docker
|
||||
running, on Mac or Linux. For "macos", you need a Mac
|
||||
machine, and note that this script is going to
|
||||
automatically install MacPython on your system, so
|
||||
don't run on your development machine. For "windows",
|
||||
you need to run in Windows, and it will build and test
|
||||
for all versions of Python at C:\PythonXX[-x64].
|
||||
--output-dir OUTPUT_DIR
|
||||
Destination folder for the wheels.
|
||||
--print-build-identifiers
|
||||
Print the build identifiers matched by the current
|
||||
invocation and exit.
|
||||
|
||||
```
|
||||
|
||||
<style>
|
||||
.toctree-l3 {
|
||||
border-left: 10px solid transparent;
|
||||
}
|
||||
|
||||
.options-toc {
|
||||
display: grid;
|
||||
grid-auto-columns: fit-content(20%) 1fr;
|
||||
grid-gap: 16px 32px;
|
||||
gap: 16px 32px;
|
||||
font-size: 90%;
|
||||
margin-bottom: 28px;
|
||||
margin-top: 28px;
|
||||
}
|
||||
.options-toc .header {
|
||||
grid-column: 1 / 3;
|
||||
font-weight: bold;
|
||||
}
|
||||
.options-toc .header:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.options-toc a.option {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
h3 code {
|
||||
font-size: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// gather the options data
|
||||
var options = {}
|
||||
var headers = []
|
||||
|
||||
$('.rst-content h3')
|
||||
.filter(function (i, el) {
|
||||
return !!$(el).text().match(/(^([A-Z0-9, _]| and )+)¶$/);
|
||||
})
|
||||
.each(function (i, el) {
|
||||
var optionName = $(el).text().replace('¶', '');
|
||||
var description = $(el).next('blockquote').text()
|
||||
var header = $(el).prevAll('h2').first().text().replace('¶', '')
|
||||
var id = el.id;
|
||||
|
||||
if (options[header] === undefined) {
|
||||
options[header] = [];
|
||||
headers.push(header);
|
||||
}
|
||||
console.log(optionName, description, header);
|
||||
|
||||
options[header].push({name: optionName, description, id});
|
||||
});
|
||||
|
||||
// write the table of contents
|
||||
|
||||
var tocTable = $('.options-toc');
|
||||
|
||||
for (var i = 0; i < headers.length; i += 1) {
|
||||
var header = headers[i];
|
||||
var headerOptions = options[header];
|
||||
|
||||
$('<div class="header">').text(header).appendTo(tocTable);
|
||||
|
||||
for (var j = 0; j < headerOptions.length; j += 1) {
|
||||
var option = headerOptions[j];
|
||||
|
||||
var optionNames = option.name.split(', ')
|
||||
|
||||
$('<div class="name">')
|
||||
.append($.map(optionNames, function (name) {
|
||||
return $('<a class="option">')
|
||||
.append(
|
||||
$('<code>').text(name)
|
||||
)
|
||||
.attr('href', '#'+option.id)
|
||||
}
|
||||
))
|
||||
.appendTo(tocTable);
|
||||
$('<div class="description">')
|
||||
.text(option.description)
|
||||
.appendTo(tocTable);
|
||||
}
|
||||
}
|
||||
|
||||
// write the markdown table for the README
|
||||
|
||||
var markdown = ''
|
||||
|
||||
markdown += '| | Option | Description |\n'
|
||||
markdown += '|---|--------|-------------|\n'
|
||||
|
||||
var prevHeader = null
|
||||
|
||||
for (var i = 0; i < headers.length; i += 1) {
|
||||
var header = headers[i];
|
||||
var headerOptions = options[header];
|
||||
for (var j = 0; j < headerOptions.length; j += 1) {
|
||||
var option = headerOptions[j];
|
||||
|
||||
if (j == 0) {
|
||||
markdown += '| **'+header+'** '
|
||||
} else {
|
||||
markdown += '| '
|
||||
}
|
||||
|
||||
var optionNames = option.name.trim().split(', ')
|
||||
var url = 'https://cibuildwheel.readthedocs.io/en/stable/options/#'+option.id;
|
||||
var namesMarkdown = $.map(optionNames, function(n) {
|
||||
return '[`'+n+'`]('+url+') '
|
||||
}).join(' ')
|
||||
|
||||
markdown += '| '+namesMarkdown+' '
|
||||
markdown += '| '+option.description.trim()+' '
|
||||
markdown += '|\n'
|
||||
}
|
||||
}
|
||||
|
||||
console.log('readme options markdown\n', markdown)
|
||||
});
|
||||
</script>
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
---
|
||||
title: 'Setup'
|
||||
---
|
||||
|
||||
# Azure Pipelines [linux/mac/windows] {: #azure-pipelines}
|
||||
|
||||
Using Azure pipelines, you can build all three platforms on the same service. Create a `azure-pipelines.yml` file in your repo.
|
||||
|
||||
> azure-pipelines.yml
|
||||
```yaml
|
||||
jobs:
|
||||
- job: linux
|
||||
pool: {vmImage: 'Ubuntu-16.04'}
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
- bash: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install cibuildwheel==1.0.0
|
||||
cibuildwheel --output-dir wheelhouse .
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs: {pathtoPublish: 'wheelhouse'}
|
||||
- job: macos
|
||||
pool: {vmImage: 'macOS-10.13'}
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
- bash: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install cibuildwheel==1.0.0
|
||||
cibuildwheel --output-dir wheelhouse .
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs: {pathtoPublish: 'wheelhouse'}
|
||||
- job: windows
|
||||
pool: {vmImage: 'vs2017-win2016'}
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
- script: choco install vcpython27 -f -y
|
||||
displayName: Install Visual C++ for Python 2.7
|
||||
- bash: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install cibuildwheel==1.0.0
|
||||
cibuildwheel --output-dir wheelhouse .
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs: {pathtoPublish: 'wheelhouse'}
|
||||
```
|
||||
|
||||
Commit this file, enable building of your repo on Azure Pipelines, and push.
|
||||
|
||||
Wheels will be stored for you and available through the Pipelines interface. For more info on this file, check out the [docs](https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema).
|
||||
|
||||
# Travis CI [linux/mac] {: #travis-ci}
|
||||
|
||||
To build Linux and Mac wheels on Travis CI, create a `.travis.yml` file in your repo.
|
||||
|
||||
> .travis.yml
|
||||
```yaml
|
||||
language: python
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- sudo: required
|
||||
services:
|
||||
- docker
|
||||
env: PIP=pip
|
||||
- os: osx
|
||||
language: generic
|
||||
env: PIP=pip2
|
||||
|
||||
script:
|
||||
- $PIP install cibuildwheel==1.0.0
|
||||
- cibuildwheel --output-dir wheelhouse
|
||||
```
|
||||
|
||||
To build on Windows too, add this matrix entry:
|
||||
```yaml
|
||||
- os: windows
|
||||
language: shell
|
||||
before_install:
|
||||
- choco install python3 --version 3.6.8 --no-progress -y
|
||||
env:
|
||||
- PATH=/c/Python36:/c/Python36/Scripts:$PATH
|
||||
```
|
||||
|
||||
Note that building Windows Python 2.7 wheels on Travis is unsupported.
|
||||
|
||||
Commit this file, enable building of your repo on Travis CI, and push.
|
||||
|
||||
Then setup a deployment method by following the [Travis CI deployment docs](https://docs.travis-ci.com/user/deployment/), or see [Delivering to PyPI](deliver-to-pypi.md). For more info on `.travis.yml`, check out the [docs](https://docs.travis-ci.com/).
|
||||
|
||||
# CircleCI [linux/mac] {: #circleci}
|
||||
|
||||
To build Linux and Mac wheels on CircleCI, create a `.circleci/config.yml` file in your repo,
|
||||
|
||||
> .circleci/config.yml
|
||||
```yaml
|
||||
version: 2
|
||||
|
||||
jobs:
|
||||
linux-wheels:
|
||||
working_directory: ~/linux-wheels
|
||||
docker:
|
||||
- image: circleci/python:3.6
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: Build the Linux wheels.
|
||||
command: |
|
||||
pip install --user cibuildwheel==1.0.0
|
||||
cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
|
||||
osx-wheels:
|
||||
working_directory: ~/osx-wheels
|
||||
macos:
|
||||
xcode: "10.0.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Build the OS X wheels.
|
||||
command: |
|
||||
pip install --user cibuildwheel==1.0.0
|
||||
cibuildwheel --output-dir wheelhouse
|
||||
- store_artifacts:
|
||||
path: wheelhouse/
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
all-tests:
|
||||
jobs:
|
||||
- linux-wheels
|
||||
- osx-wheels
|
||||
```
|
||||
|
||||
Commit this file, enable building of your repo on CircleCI, and push.
|
||||
|
||||
!!! note
|
||||
CircleCI doesn't enable free macOS containers for open source by default, but you can ask for access. See [here](https://circleci.com/docs/2.0/oss/#overview) for more information.
|
||||
|
||||
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.
|
||||
|
||||
# AppVeyor [windows] {: #appveyor}
|
||||
|
||||
To build Windows wheels on AppVeyor, create an `appveyor.yml` file in your repo.
|
||||
|
||||
> appveyor.yml
|
||||
|
||||
```yaml
|
||||
build_script:
|
||||
- pip install cibuildwheel==1.0.0
|
||||
- cibuildwheel --output-dir wheelhouse
|
||||
artifacts:
|
||||
- path: "wheelhouse\\*.whl"
|
||||
name: Wheels
|
||||
```
|
||||
|
||||
Commit this file, enable building of your repo on AppVeyor, and push.
|
||||
|
||||
AppVeyor will store the built wheels for you - you can access them from the project console. Alternatively, you may want to store them in the same place as the Travis CI build. See [AppVeyor deployment docs](https://www.appveyor.com/docs/deployment/) for more info, or see [Delivering to PyPI](deliver-to-pypi.md) below.
|
||||
|
||||
For more info on this config file, check out the [docs](https://www.appveyor.com/docs/).
|
||||
|
||||
> ⚠️ Got an error? Check the [FAQ](faq.md).
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
$('.toctree-l2 a, .rst-content h1').each(function(i, el) {
|
||||
var text = $(el).text()
|
||||
var match = text.match(/(.*) \[([a-z/]+)\]/);
|
||||
|
||||
if (match) {
|
||||
var iconHTML = $.map(match[2].split('/'), function(ident) {
|
||||
switch (ident) {
|
||||
case 'linux':
|
||||
return '<i class="fa fa-linux" aria-hidden="true"></i>'
|
||||
case 'windows':
|
||||
return '<i class="fa fa-windows" aria-hidden="true"></i>'
|
||||
case 'mac':
|
||||
return '<i class="fa fa-apple" aria-hidden="true"></i>'
|
||||
}
|
||||
}).join(' ');
|
||||
|
||||
$(el).append(
|
||||
$('<div>')
|
||||
.append(iconHTML)
|
||||
.css({float: 'right'})
|
||||
)
|
||||
$(el).contents()
|
||||
.filter(function(){ return this.nodeType == 3; }).first()
|
||||
.replaceWith(match[1]);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
site_name: cibuildwheel
|
||||
docs_dir: docs
|
||||
theme:
|
||||
name: readthedocs
|
||||
highlightjs: true
|
||||
hljs_languages:
|
||||
- yaml
|
||||
repo_url: https://github.com/joerick/cibuildwheel
|
||||
|
||||
extra_css:
|
||||
- extra.css
|
||||
|
||||
extra_javascript:
|
||||
- extra.js
|
||||
|
||||
nav:
|
||||
- Home: index.md
|
||||
- setup.md
|
||||
- options.md
|
||||
- deliver-to-pypi.md
|
||||
- faq.md
|
||||
- contributing.md
|
||||
|
||||
markdown_extensions:
|
||||
- fenced_code
|
||||
- toc:
|
||||
permalink: True
|
||||
- attr_list
|
||||
- admonition
|
||||
|
||||
plugins:
|
||||
- importmarkdown
|
||||
@@ -1,2 +1,4 @@
|
||||
-e .
|
||||
-e ./docs/mkdocs_include_markdown_plugin
|
||||
pytest
|
||||
mkdocs==1.0.4
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 0.11.1
|
||||
current_version = 1.0.0
|
||||
commit = True
|
||||
tag = True
|
||||
message = Bump version
|
||||
@@ -12,6 +12,10 @@ message = Bump version
|
||||
search = cibuildwheel=={current_version}
|
||||
replace = cibuildwheel=={new_version}
|
||||
|
||||
[bumpversion:file:docs/setup.md]
|
||||
search = cibuildwheel=={current_version}
|
||||
replace = cibuildwheel=={new_version}
|
||||
|
||||
[bdist_wheel]
|
||||
universal = 1
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ except ImportError:
|
||||
|
||||
setup(
|
||||
name='cibuildwheel',
|
||||
version='0.11.1',
|
||||
version='1.0.0',
|
||||
install_requires=['bashlex!=0.13'],
|
||||
description="Build Python wheels on CI with minimal configuration.",
|
||||
long_description='For readme please see http://github.com/joerick/cibuildwheel',
|
||||
@@ -21,6 +21,8 @@ setup(
|
||||
package_data={
|
||||
'cibuildwheel': ['resources/*'],
|
||||
},
|
||||
# Supported python versions
|
||||
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
|
||||
keywords='ci wheel packaging pypi travis appveyor macos linux windows',
|
||||
classifiers=[
|
||||
'Intended Audience :: Developers',
|
||||
|
||||
@@ -17,6 +17,10 @@ def test():
|
||||
def test_build_identifiers():
|
||||
# check that the number of expected wheels matches the number of build
|
||||
# identifiers
|
||||
expected_wheels = utils.expected_wheels('spam', '0.1.0')
|
||||
# after adding CIBW_MANYLINUX_IMAGE to support manylinux2010, there
|
||||
# can be multiple wheels for each wheel, though, so we need to limit
|
||||
# the expected wheels
|
||||
expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0')
|
||||
if not '-manylinux' in w or '-manylinux1' in w]
|
||||
build_identifiers = utils.cibuildwheel_get_build_identifiers(project_dir)
|
||||
assert len(expected_wheels) == len(build_identifiers)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import os, subprocess
|
||||
import pytest
|
||||
import utils
|
||||
|
||||
def test():
|
||||
@@ -12,8 +13,43 @@ def test():
|
||||
'CIBW_TEST_COMMAND': 'false || nosetests {project}/test',
|
||||
'CIBW_TEST_COMMAND_WINDOWS': 'nosetests {project}/test',
|
||||
})
|
||||
|
||||
|
||||
# also check that we got the right wheels
|
||||
expected_wheels = utils.expected_wheels('spam', '0.1.0')
|
||||
actual_wheels = os.listdir('wheelhouse')
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
|
||||
def test_extras_require():
|
||||
project_dir = os.path.dirname(__file__)
|
||||
|
||||
# build and test the wheels
|
||||
utils.cibuildwheel_run(project_dir, add_env={
|
||||
'CIBW_TEST_EXTRAS': 'test',
|
||||
# the 'false ||' bit is to ensure this command runs in a shell on
|
||||
# mac/linux.
|
||||
'CIBW_TEST_COMMAND': 'false || nosetests {project}/test',
|
||||
'CIBW_TEST_COMMAND_WINDOWS': 'nosetests {project}/test',
|
||||
})
|
||||
|
||||
# also check that we got the right wheels
|
||||
expected_wheels = utils.expected_wheels('spam', '0.1.0')
|
||||
actual_wheels = os.listdir('wheelhouse')
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
|
||||
def test_failing_test():
|
||||
'''Ensure a failing test causes cibuildwheel to error out and exit'''
|
||||
project_dir = os.path.dirname(__file__)
|
||||
|
||||
with pytest.raises(subprocess.CalledProcessError):
|
||||
utils.cibuildwheel_run(project_dir, add_env={
|
||||
'CIBW_TEST_COMMAND': 'false',
|
||||
# manylinux1 has a version of bash that's been shown to have
|
||||
# problems with this, so let's check that.
|
||||
'CIBW_MANYLINUX_I686_IMAGE': 'manylinux1',
|
||||
'CIBW_MANYLINUX_X86_64_IMAGE': 'manylinux1',
|
||||
})
|
||||
|
||||
assert len(os.listdir('wheelhouse'))
|
||||
|
||||
|
||||
@@ -3,5 +3,6 @@ from setuptools import setup, Extension
|
||||
setup(
|
||||
name="spam",
|
||||
ext_modules=[Extension('spam', sources=['spam.c'])],
|
||||
extras_require={'test': ['nose']},
|
||||
version="0.1.0",
|
||||
)
|
||||
|
||||
@@ -7,11 +7,11 @@ def test():
|
||||
# build the wheels
|
||||
utils.cibuildwheel_run(project_dir, add_env={
|
||||
'CIBW_BUILD': 'cp3?-*',
|
||||
'CIBW_SKIP': 'cp34-*',
|
||||
'CIBW_SKIP': 'cp37-*',
|
||||
})
|
||||
|
||||
# check that we got the right wheels. There should be no 2.7 or 3.4.
|
||||
# check that we got the right wheels. There should be no 2.7 or 3.7.
|
||||
expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0')
|
||||
if ('-cp3' in w) and ('-cp34' not in w)]
|
||||
if ('-cp3' in w) and ('-cp37' not in w)]
|
||||
actual_wheels = os.listdir('wheelhouse')
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
@@ -5,14 +5,17 @@ def test():
|
||||
project_dir = os.path.dirname(__file__)
|
||||
|
||||
if utils.platform != 'linux':
|
||||
pytest.skip('the docker test is only relevant to the linux build')
|
||||
pytest.skip('the test is only relevant to the linux build')
|
||||
|
||||
utils.cibuildwheel_run(project_dir, add_env={
|
||||
'CIBW_MANYLINUX1_X86_64_IMAGE': 'dockcross/manylinux-x64',
|
||||
'CIBW_MANYLINUX1_I686_IMAGE': 'dockcross/manylinux-x86',
|
||||
'CIBW_MANYLINUX_X86_64_IMAGE': 'dockcross/manylinux2010-x64',
|
||||
'CIBW_MANYLINUX_I686_IMAGE': 'dockcross/manylinux1-x86',
|
||||
'CIBW_BEFORE_BUILD': '/opt/python/cp36-cp36m/bin/pip install -U auditwheel', # Currently necessary on dockcross images to get auditwheel 2.1 supporting AUDITWHEEL_PLAT
|
||||
'CIBW_ENVIRONMENT': 'AUDITWHEEL_PLAT=`if [ $(uname -i) == "x86_64" ]; then echo "manylinux2010_x86_64"; else echo "manylinux1_i686"; fi`',
|
||||
})
|
||||
|
||||
# also check that we got the right wheels built
|
||||
expected_wheels = utils.expected_wheels('spam', '0.1.0')
|
||||
expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0')
|
||||
if '-manylinux2010_i686' not in w]
|
||||
actual_wheels = os.listdir('wheelhouse')
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import os, pytest
|
||||
import utils
|
||||
|
||||
def test():
|
||||
project_dir = os.path.dirname(__file__)
|
||||
|
||||
if utils.platform != 'linux':
|
||||
pytest.skip('the docker test is only relevant to the linux build')
|
||||
|
||||
# build the wheels
|
||||
# CFLAGS environment veriable is ecessary to fail on 'malloc_info' (on manylinux1) during compilation/linking,
|
||||
# rather than when dynamically loading the Python
|
||||
utils.cibuildwheel_run(project_dir, add_env={
|
||||
'CIBW_ENVIRONMENT': 'CFLAGS="$CFLAGS -Werror=implicit-function-declaration"',
|
||||
})
|
||||
|
||||
# also check that we got the right wheels
|
||||
expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0')
|
||||
if not '-manylinux' in w or '-manylinux2010' in w]
|
||||
actual_wheels = os.listdir('wheelhouse')
|
||||
assert set(actual_wheels) == set(expected_wheels)
|
||||
@@ -0,0 +1,7 @@
|
||||
from setuptools import setup, Extension
|
||||
|
||||
setup(
|
||||
name="spam",
|
||||
ext_modules=[Extension('spam', sources=['spam.c'])],
|
||||
version="0.1.0",
|
||||
)
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <Python.h>
|
||||
#if defined(__linux__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
static PyObject *
|
||||
spam_system(PyObject *self, PyObject *args)
|
||||
{
|
||||
const char *command;
|
||||
int sts = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &command))
|
||||
return NULL;
|
||||
|
||||
#if defined(__linux__)
|
||||
sts = malloc_info(0, stdout);
|
||||
#endif
|
||||
if (sts == 0) {
|
||||
sts = system(command);
|
||||
}
|
||||
return PyLong_FromLong(sts);
|
||||
}
|
||||
|
||||
/* Module initialization */
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
|
||||
#define MOD_DEF(m, name, doc, methods, module_state_size) \
|
||||
static struct PyModuleDef moduledef = { \
|
||||
PyModuleDef_HEAD_INIT, name, doc, module_state_size, methods, }; \
|
||||
m = PyModule_Create(&moduledef);
|
||||
#define MOD_RETURN(m) return m;
|
||||
#else
|
||||
#define MOD_INIT(name) PyMODINIT_FUNC init##name(void)
|
||||
#define MOD_DEF(m, name, doc, methods, module_state_size) \
|
||||
m = Py_InitModule3(name, methods, doc);
|
||||
#define MOD_RETURN(m) return;
|
||||
#endif
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
{"system", (PyCFunction)spam_system, METH_VARARGS,
|
||||
"Execute a shell command."},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
MOD_INIT(spam)
|
||||
{
|
||||
PyObject* m;
|
||||
|
||||
MOD_DEF(m,
|
||||
"spam",
|
||||
"Example module",
|
||||
module_methods,
|
||||
-1)
|
||||
|
||||
MOD_RETURN(m)
|
||||
}
|
||||
+27
-14
@@ -6,7 +6,8 @@ This file is added to the PYTHONPATH in the test runner at bin/run_test.py.
|
||||
|
||||
import subprocess, sys, os
|
||||
|
||||
IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
|
||||
IS_WINDOWS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
|
||||
IS_WINDOWS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows'
|
||||
|
||||
|
||||
def cibuildwheel_get_build_identifiers(project_path, env=None):
|
||||
@@ -25,14 +26,14 @@ def cibuildwheel_get_build_identifiers(project_path, env=None):
|
||||
|
||||
def cibuildwheel_run(project_path, env=None, add_env=None):
|
||||
'''
|
||||
Runs cibuildwheel as a subprocess, building the project at project_path.
|
||||
|
||||
Runs cibuildwheel as a subprocess, building the project at project_path.
|
||||
|
||||
Uses the current Python interpreter.
|
||||
Configure settings using env.
|
||||
'''
|
||||
if env is None:
|
||||
env = os.environ.copy()
|
||||
|
||||
|
||||
if add_env is not None:
|
||||
env.update(add_env)
|
||||
|
||||
@@ -50,45 +51,57 @@ def expected_wheels(package_name, package_version):
|
||||
templates = [
|
||||
'{package_name}-{package_version}-cp27-cp27m-manylinux1_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp27-cp27mu-manylinux1_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp34-cp34m-manylinux1_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp35-cp35m-manylinux1_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp36-cp36m-manylinux1_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp37-cp37m-manylinux1_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp38-cp38-manylinux1_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp27-cp27m-manylinux2010_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp27-cp27mu-manylinux2010_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp35-cp35m-manylinux2010_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp36-cp36m-manylinux2010_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp37-cp37m-manylinux2010_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp38-cp38-manylinux2010_x86_64.whl',
|
||||
'{package_name}-{package_version}-cp27-cp27m-manylinux1_i686.whl',
|
||||
'{package_name}-{package_version}-cp27-cp27mu-manylinux1_i686.whl',
|
||||
'{package_name}-{package_version}-cp34-cp34m-manylinux1_i686.whl',
|
||||
'{package_name}-{package_version}-cp35-cp35m-manylinux1_i686.whl',
|
||||
'{package_name}-{package_version}-cp36-cp36m-manylinux1_i686.whl',
|
||||
'{package_name}-{package_version}-cp37-cp37m-manylinux1_i686.whl',
|
||||
'{package_name}-{package_version}-cp38-cp38-manylinux1_i686.whl',
|
||||
'{package_name}-{package_version}-cp27-cp27m-manylinux2010_i686.whl',
|
||||
'{package_name}-{package_version}-cp27-cp27mu-manylinux2010_i686.whl',
|
||||
'{package_name}-{package_version}-cp35-cp35m-manylinux2010_i686.whl',
|
||||
'{package_name}-{package_version}-cp36-cp36m-manylinux2010_i686.whl',
|
||||
'{package_name}-{package_version}-cp37-cp37m-manylinux2010_i686.whl',
|
||||
'{package_name}-{package_version}-cp38-cp38-manylinux2010_i686.whl',
|
||||
]
|
||||
elif platform == 'windows':
|
||||
templates = [
|
||||
'{package_name}-{package_version}-cp27-cp27m-win32.whl',
|
||||
'{package_name}-{package_version}-cp34-cp34m-win32.whl',
|
||||
'{package_name}-{package_version}-cp35-cp35m-win32.whl',
|
||||
'{package_name}-{package_version}-cp36-cp36m-win32.whl',
|
||||
'{package_name}-{package_version}-cp37-cp37m-win32.whl',
|
||||
'{package_name}-{package_version}-cp38-cp38-win32.whl',
|
||||
'{package_name}-{package_version}-cp27-cp27m-win_amd64.whl',
|
||||
'{package_name}-{package_version}-cp34-cp34m-win_amd64.whl',
|
||||
'{package_name}-{package_version}-cp35-cp35m-win_amd64.whl',
|
||||
'{package_name}-{package_version}-cp36-cp36m-win_amd64.whl',
|
||||
'{package_name}-{package_version}-cp37-cp37m-win_amd64.whl',
|
||||
'{package_name}-{package_version}-cp38-cp38-win_amd64.whl',
|
||||
]
|
||||
elif platform == 'macos':
|
||||
templates = [
|
||||
'{package_name}-{package_version}-cp27-cp27m-macosx_10_6_intel.whl',
|
||||
'{package_name}-{package_version}-cp34-cp34m-macosx_10_6_intel.whl',
|
||||
'{package_name}-{package_version}-cp35-cp35m-macosx_10_6_intel.whl',
|
||||
'{package_name}-{package_version}-cp36-cp36m-macosx_10_6_intel.whl',
|
||||
'{package_name}-{package_version}-cp37-cp37m-macosx_10_6_intel.whl',
|
||||
'{package_name}-{package_version}-cp38-cp38-macosx_10_9_x86_64.whl',
|
||||
]
|
||||
else:
|
||||
raise Exception('unsupported platform')
|
||||
|
||||
if IS_RUNNING_ON_AZURE:
|
||||
# Python 3.4 isn't supported on Azure.
|
||||
templates = [t for t in templates if '-cp34-' not in t]
|
||||
|
||||
|
||||
if IS_WINDOWS_RUNNING_ON_TRAVIS:
|
||||
# Python 2.7 isn't supported on Travis.
|
||||
templates = [t for t in templates if '-cp27-' not in t]
|
||||
|
||||
return [filename.format(package_name=package_name, package_version=package_version)
|
||||
for filename in templates]
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
from cibuildwheel.environment import parse_environment
|
||||
|
||||
|
||||
@@ -37,12 +38,15 @@ def test_inheritance():
|
||||
def test_shell_eval():
|
||||
environment_recipe = parse_environment('VAR="$(echo "a test" string)"')
|
||||
|
||||
env_copy = os.environ.copy()
|
||||
env_copy.pop('VAR', None)
|
||||
|
||||
environment_dict = environment_recipe.as_dictionary(
|
||||
prev_environment={}
|
||||
prev_environment=env_copy
|
||||
)
|
||||
environment_cmds = environment_recipe.as_shell_commands()
|
||||
|
||||
assert environment_dict == {'VAR': '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():
|
||||
|
||||
Reference in New Issue
Block a user