Compare commits

..
334 Commits
Author SHA1 Message Date
Joe Rickerby 7709989603 Bump version 2019-12-07 14:58:10 +00:00
Joe Rickerby 31e67c4f1f Update changelog 2019-12-07 14:58:00 +00:00
Joe Rickerby 11bde36627 Merge pull request #234 from Czaki/fix_setup_cfg
change directory to not conflict with setup.cfg of package
2019-12-07 14:35:38 +00:00
Grzegorz Bokota 5941ba7daf add tests 2019-12-05 21:13:11 +01:00
Grzegorz Bokota c1df977e11 change directory to not conflict with setup.cfg of package 2019-12-03 22:07:47 +01:00
Matthieu Darbois 1dbb12daaa Add manylinux2014 x86_64/i686 (#215) 2019-12-02 11:07:56 +01:00
Joe Rickerby a005e263fc Merge pull request #233 from Czaki/fix_doc_environment
Add example of usage more than one environment variable
2019-12-02 08:54:26 +00:00
Grzegorz Bokota 2a1081c5e5 update docs with information about more than one environment variable. 2019-12-01 21:45:08 +01:00
Joe Rickerby 9c908daf27 Merge pull request #226 from Czaki/fix_platform_bug
Add better protection to unittest to be shure that it will create no changes on developer machine
2019-11-29 09:34:52 +00:00
Joe Rickerby 054be2eff2 Merge pull request #228 from SethMMorton/update-travis-examples
Update travis examples
2019-11-28 22:45:09 +00:00
Seth Morton 20ba988b72 Add an example folder with Travis-CI examples
I have placed two example Travis-CI configurations in an examples/
folder. The first is the same as in the README, and the second shows how
to both test and deploy in two stages.

I am hoping that examples might be added for other CI providers as well,
so that users can see different approaches to building and deploying
wheels.
2019-11-25 18:59:07 -08:00
Seth Morton 190b013c61 Update Travis CI examples
For a more granular view of why each of these changes were made, please
see https://github.com/joerick/cibuildwheel-autopypi-example/pull/5.

High-level overview:
 - Adding Windows support
 - Remove "sudo: required" for linux
 - Use "python -m pip" instead of using an environment variable
 - Add "install:" and "after_success:" steps so that errors get handled
   and reported properly
 - Rename "matrix:" to "jobs:" as this is the now preferred keyword
2019-11-25 15:08:18 -08:00
Grzegorz Bokota c966c6d098 Add mock for better protection of unit tests launch.
change behavior of main function to always end with exit.
2019-11-24 12:17:08 +01:00
Grzegorz Bokota d2700bc3b4 fix UnboundLocalError instead of proper error message (#221)
* fix UnboundLocalError: local variable 'platform' referenced before assignment
* add test to protect against regression
2019-11-21 22:45:33 +01:00
Matthieu Darbois 09e72800c6 Run each test using a temporary directory (#217) 2019-11-20 22:20:53 +01:00
Joe Rickerby 2b62eef9e7 Merge pull request #211 from nsoranzo/delocate_command
Add `CIBW_REPAIR_WHEEL_COMMAND` env variable
2019-11-20 19:58:19 +00:00
Nicola Soranzo 85cba9b1eb Move Platform-specific variants before Examples 2019-11-17 19:08:22 +00:00
Nicola Soranzo 402ec9e4ac Address one more review comment 2019-11-15 02:56:30 +00:00
Nicola Soranzo e9fd9eaead Address @joerick's comments 2019-11-15 02:27:39 +00:00
Nicola Soranzo 0e04fafd3a Add CIBW_REPAIR_COMMAND env variable
to allow different options for auditwheel/delocate, alternative
commands and a future Windows equivalent.

Fix https://github.com/joerick/cibuildwheel/issues/191 .
2019-11-14 12:10:55 +00:00
Yannick Jadoul 34515b78c6 Merge pull request #209 from YannickJadoul/silence-script-not-on-path-warnings
Avoid script location warnings on Windows
2019-11-14 11:59:40 +01:00
Yannick Jadoul 7d99ccfc7b Collapse multiple 'pip install's into one in windows.py and macos.py, and replace full path by 'python' in windows.py 2019-11-12 23:47:06 +01:00
Yannick Jadoul dc01231301 Replace a few shell invocations by simple_shell in windows.py 2019-11-12 22:25:54 +01:00
Matthieu Darbois 96a2505e78 Merge pull request #207 from mayeut/doc-appveyor-linux
Update doc for AppVeyor on linux
2019-11-12 22:11:27 +01:00
Yannick Jadoul d3fd087166 Run python get-pip.py with Scripts directory in PATH to avoid warnings, and reorder steps to match macOS 2019-11-12 17:05:37 +01:00
mayeut b3f82d52cc Update doc for AppVeyor on linux 2019-11-12 01:20:06 +01:00
Matthieu Darbois 7d90a2f16b Merge pull request #204 from mayeut/appveyor-linux
Rework platform detection to ignore CI provider to determine windows/linux/macos.
A check is still present to check if CI is running or not.
2019-11-11 22:24:52 +01:00
mayeut f4318e15b7 Keep CI check for platform auto 2019-11-11 21:49:16 +01:00
mayeut d3450e84ac Rework platform detection to ignore CI provider.
CI provider is now mostly irrelevant, rework platform detection with that in mind.
Run linux test in AppVeyor
2019-11-10 23:40:20 +01:00
Joe Rickerby a3e9b7b8ec Embed readme in project for PyPI 2019-11-10 19:13:49 +00:00
Joe Rickerby 1a9c6a5f66 Add azure pipelines status badge 2019-11-10 19:02:06 +00:00
Joe Rickerby c44a084a44 Really fix link 2019-11-10 19:01:58 +00:00
Joe Rickerby 1e102b9bc5 Fix link 2019-11-10 15:54:17 +00:00
Joe Rickerby 46f1906e2d Add docs badge 2019-11-10 15:52:01 +00:00
Joe Rickerby 79c480b896 Update changelog 2019-11-10 15:47:33 +00:00
Joe Rickerby 734ca6bfbd Remove @tgarc from maintainers 2019-11-10 15:45:34 +00:00
Joe Rickerby beda529298 Bump version 2019-11-10 15:16:37 +00:00
Joe Rickerby 292bf42cb0 Merge pull request #169 from joerick/docs
Pull docs into a dedicated documentation site
2019-11-10 15:14:09 +00:00
Joe Rickerby a8d1e69783 Merge pull request #200 from joerick/test-bash-errexit-again
Add check that failing tests fail on manylinux1 specifically
2019-11-10 15:07:45 +00:00
Joe Rickerby ab53f06bc6 Merge pull request #201 from mayeut/remove-macos-travis-python2
Remove macOS python2 on Travis CI
2019-11-10 15:04:01 +00:00
Joe Rickerby 053a154d1d Merge pull request #197 from mayeut/cibw-dir
Use specific cibw directory on Windows to prevent collisions with installed software
2019-11-10 15:03:09 +00:00
Joe Rickerby 7d08bac099 Add note about command line option 2019-11-10 14:57:21 +00:00
Joe Rickerby 8e274700f4 Reformat examples on the options page and add a comment for each one 2019-11-10 14:54:56 +00:00
Joe Rickerby 22ae365ae9 Clean up plugin 2019-11-10 13:22:44 +00:00
Joe Rickerby ccd22e5a5a Allow line breaks in table headers 2019-11-10 13:22:35 +00:00
Joe Rickerby 2692162617 Improve BUILD/SKIP options formatting 2019-11-10 13:21:05 +00:00
Joe Rickerby d112b343e1 Fix link 2019-11-10 13:20:33 +00:00
Joe Rickerby 7ac8798d26 fix element id 2019-11-10 12:08:14 +00:00
Joe Rickerby a41ce8e4a0 Add options summary to readme 2019-11-09 19:41:42 +00:00
Joe Rickerby 07fd1a3203 Formatting and polish 2019-11-09 19:38:59 +00:00
mayeut 81ce8116b5 Remove macos python2 on travis-ci
Testing with python2 is already done on circle-ci
2019-11-09 20:18:39 +01:00
mayeut c82330b0bc Use specific cibw directory on Windows to prevent collisions with installed software 2019-11-09 19:44:14 +01:00
Joe Rickerby 50a518eac4 Merge remote-tracking branch 'origin/master' into test-bash-errexit-again 2019-11-09 18:41:56 +00:00
Joe Rickerby 42d1610d52 Merge pull request #175 from GjjvdBurg/returncode
Make sure build fails when test command fails
2019-11-09 18:41:26 +00:00
Joe Rickerby ac51d22884 Merge remote-tracking branch 'origin/master' into docs 2019-11-09 18:23:41 +00:00
Joe Rickerby c42cca1c86 Add test that failing tests fail on manylinux1 specifically 2019-11-09 18:07:46 +00:00
Joe Rickerby b51434b5a8 Merge pull request #199 from mayeut/cibuildwheel-pythons
Tests cibuildwheel across different python versions
2019-11-09 17:49:00 +00:00
mayeut 7dee79a96b Add python_requires metadata 2019-11-09 12:38:38 +01:00
mayeut ce93a03098 Fix tests on Windows Python 3.8 2019-11-09 12:16:25 +01:00
mayeut 319aee73f2 Force python 3.8 on Azure 2019-11-09 11:19:02 +01:00
Gertjan van den Burg 5210ad3610 clarify comment at if statement 2019-11-08 10:53:18 +00:00
Gertjan van den Burg def8f9a2e3 Remove errexit flag for test command subshell 2019-11-08 10:53:06 +00:00
Gertjan van den Burg f716f87a04 Merge branch 'master' into returncode 2019-11-08 10:51:49 +00:00
Joe Rickerby 0375e92110 Merge pull request #188 from metabolize/fix-appveyor-setup-doc-outline
Readme: Fix the outline for Appveyor setup
2019-11-05 19:28:05 +00:00
Gertjan van den Burg 560c1adeb7 Merge branch 'master' into returncode 2019-11-05 17:09:17 +00:00
Paul Melnikow 3c9875db19 Readme: Remove obsolete bullet for Appveyor setup 2019-11-05 09:41:23 -05:00
Joe Rickerby 89e2ac7ebf Merge pull request #180 from mayeut/nuget
Adding Python 3.8, Always use nuget to install python on Windows
2019-11-05 09:06:20 +00:00
mayeut 05ab66cf97 Fix documentation for macOS python 3.8 2019-11-04 22:49:53 +01:00
mayeut 104dcf1d37 Add python 3.8 support 2019-11-04 22:22:40 +01:00
mayeut f2ef7a6169 Always use nuget to install python on Windows 2019-11-04 22:08:30 +01:00
mayeut 58048b4bb1 Remove trailing-spaces from README.md
Also replace double-space by a backslash to show intent of a line-break.
2019-11-04 22:05:24 +01:00
Joe Rickerby 332674a382 Merge pull request #168 from mayeut/drop-python-3.4
Drop python 3.4
2019-11-04 19:15:05 +00:00
Joe Rickerby 88ef908bad Merge remote-tracking branch 'origin/master' into docs
Manually merged updates to README.md across to docs

# Conflicts:
#	README.md
2019-11-03 19:38:18 +00:00
Joe Rickerby eb8c926eba Remove unused CSS and visual tweaks 2019-11-03 19:13:56 +00:00
Joe Rickerby 73cba728a1 Have the page generate markdown for the README 2019-11-03 19:06:48 +00:00
Joe Rickerby 1446529f7c Sort out page titles 2019-11-03 19:06:33 +00:00
Joe Rickerby 51649fd806 Add page from wiki to 'tips and tricks' page 2019-11-03 18:40:14 +00:00
Joe Rickerby f55b663ea7 Add requirement for our markdown plugin 2019-11-03 18:35:17 +00:00
Joe Rickerby 2360c406bf Add JS code to generate a table of contents 2019-11-03 18:35:06 +00:00
Joe Rickerby 5db3763b2d Add plugin to import sections of readme into the documentation 2019-11-03 18:30:15 +00:00
mayeut bb0cad404b Drop python 3.4
Python 3.4 reached the end of its life on 16 March 2019. It's about time to drop support for Python 3.4.
2019-10-26 15:53:44 +02:00
Yannick Jadoul a6164f765c Merge pull request #183 from mayeut/macos-python3
Do not update brew python3
2019-10-26 15:47:08 +02:00
mayeut 892c7b4d9c Update .travis.yml 2019-10-26 14:45:24 +02:00
Joe Rickerby 3fcb902fd9 Merge pull request #171 from mayeut/python-3.7.5
Update CPython 2.7 from 2.7.16 to 2.7.17 & 3.7 from 3.7.4 to 3.7.5 on macOS
2019-10-25 10:06:09 +01:00
Yannick Jadoul 8c9345fa1f Updated line of README mistakenly claiming Windows is not supported on Travis CI 2019-10-24 14:00:28 +02:00
mayeut 5eab3620c9 Update CPython 2.7 from 2.7.16 to 2.7.17 & 3.7 from 3.7.4 to 3.7.5 on macOS 2019-10-23 22:59:17 +02:00
Grzegorz BokotaandJoe Rickerby 80974e5b39 Build Python wheels for windows on travis (#160)
* upgrade for windows on travis

* Install python on travis windows, update readme, update tests

* update readme, travis config and clean code

* install python inside cibuildwheel run

* use register to get python path

* fixes from review

* fix pip version

* use nuget for instal python

* clean code

* Update cibuildwheel/windows.py

Co-Authored-By: Joe Rickerby <joerick@mac.com>

* fixes from review

* Final bits of tidy up
2019-10-23 21:53:10 +01:00
Joe Rickerby 4f705b7cc9 Merge pull request #177 from joerick/failing-test-test
Add failing test check
2019-10-23 21:35:44 +01:00
Gertjan van den Burg e0eb375449 Returncode fix (#1)
Some trial and error to make sure it works reliably.

* remove test_retcode
* debug local bash settings
* set errexit explicitly in subshell
* set errexit also in the subshell in parenthesis
* debugging
* more debugging (exit code of sh)
* is the venv subshell returning exit 1?
* what if we remove the additional subshell?
* then we need to unquote the command
* if statement needs test command quoted
* simple if statement
* echo command needs to be removed of course
* remove debug statements
* check if setting errexit here is needed
* these settings can be removed
  At this point ("before") the shell already has errexit set.
* setting errexit in the sh invocation is needed
  This is not inherited, so it's good to specify it.
* just double checking that the subshell doesn't exit
* use solution from fvue.nl
* Solution doesn't seem to work, even popd is run
  So now I'm putting back the if statement, it seems
  to be the simplest and most effective solution.
* add a comment
* prove that errexit is necessary
* errexit is indeed needed for chaining
2019-10-21 11:42:43 +01:00
Joe Rickerby bbecbe43ec Add failing test check 2019-10-20 20:45:25 +01:00
Joe Rickerby 46865a5f40 Options page rework (incomplete) 2019-10-20 20:39:50 +01:00
Joe Rickerby b577c5f00f Misc copy edits 2019-10-20 19:43:13 +01:00
Joe Rickerby ee2a90880a Merge pull request #155 from YannickJadoul/manylinux2010-alternative
Adding support for building manylinux2010 wheels - alternative
2019-10-20 19:29:19 +01:00
Yannick Jadoul 31d89377da Updated README with new CIBW_MANYLINUX_*_IMAGE options 2019-10-19 14:07:50 +02:00
Gertjan van den Burg 0c33a58579 failing test breaks out of subshell 2019-10-18 11:45:48 +01:00
Gertjan van den Burg 3842cfd853 Attempt at getting the retcode of the test process 2019-10-18 11:31:48 +01:00
Yannick Jadoul 2e0dc40e3f Adding manylinux2010_i686 image and simplifying tests' utils.expected_wheels() 2019-10-16 01:15:09 +02:00
Yannick Jadoul c6f1382813 Making manylinux1 still the default for manylinux_i686 builds 2019-10-16 00:35:20 +02:00
Yannick Jadoul 1220fbbd4b Adding detection of old CIBW_MANYLINUX1_*_IMAGE options and manylinux1-* build identifiers in CIBW_BUILD and CIBW_SKIP 2019-10-16 00:35:20 +02:00
Yannick Jadoul 179148b0e5 Updated preset values for CIBW_MANYLINUX_*_IMAGE, fixed skip message in 08_manylinux2010_only test, and added clarifying comment on multiple wheels in Linux bash script 2019-10-16 00:35:20 +02:00
Yannick Jadoul 4536b23a1d Adding test accessing manylinux2010-only ABI 2019-10-16 00:34:13 +02:00
Yannick Jadoul 4571262803 Adapting Linux bash script for multiple output wheels from auditwheel 2019-10-16 00:34:13 +02:00
Yannick Jadoul 27517cd8a0 Updating test 06_docker_images to use new CIBW_MANYLINUX_*_IMAGE options 2019-10-16 00:33:45 +02:00
Yannick Jadoul 54dd72de66 Copying all created manylinux wheels to the output directory 2019-10-16 00:33:45 +02:00
Yannick Jadoul 7978247fa7 Fixing tests still failing as manylinux1 wheels are also produced by auditwheel 2019-10-16 00:33:45 +02:00
Yannick Jadoul 7cadc6374a Fixing tests failing because of new manylinux2010 default 2019-10-16 00:33:45 +02:00
Yannick Jadoul e194dad0da Alternative proposal to generalize manylinux builds and support manylinux2010 2019-10-16 00:33:45 +02:00
Joe Rickerby 5f416b194a Merge pull request #164 from astrofrog/virtualenv-notox
Run tests in clean virtual environment [version without tox]
2019-10-13 21:24:19 +01:00
Joe Rickerby 2a244616ad windows: only make venv when test is defined and isolate env vars 2019-10-12 10:47:00 +01:00
Joe Rickerby bfa3eebb7f Remove redundant if clause 2019-10-12 10:44:47 +01:00
Joe Rickerby b0c2fd8af2 macos: only make venv when test is defined and isolate env vars 2019-10-12 10:35:45 +01:00
Joe Rickerby cf90846161 linux: run tests in a subshell, only create env if test defined 2019-10-12 10:17:28 +01:00
Joe Rickerby 89bb2d352d Add docs links to the setup guide 2019-10-07 09:15:59 +01:00
Joe Rickerby c1572e4ff4 Ensure the pinned versions in docs are bumped 2019-10-06 23:09:34 +01:00
Joe Rickerby 1741d7ce1f Docs samples should pin versions 2019-10-06 23:05:55 +01:00
Joe Rickerby 05385b1cb0 Add readthedocs config 2019-10-06 22:57:41 +01:00
Joe Rickerby 3ba7aa3532 Copy improvements 2019-10-06 20:36:37 +01:00
Joe Rickerby bb2a5f8d17 Formatting improvements 2019-10-06 20:36:21 +01:00
Joe Rickerby 44d0dcba12 Update license copyright 2019-10-06 11:38:48 +01:00
Joe Rickerby 4c86af69a5 Readme tweaks 2019-10-06 11:38:36 +01:00
Joe Rickerby 93663d19df Move changelog back into the readme 2019-10-06 11:38:24 +01:00
Joe Rickerby c006fdab36 Migrate more README over to the docs 2019-10-02 09:49:31 +01:00
Joe Rickerby d280f0f16a Add options to docs 2019-09-29 21:53:18 +01:00
Joe Rickerby b49754dc7d mkdocs setup 2019-09-29 20:55:41 +01:00
Joe Rickerby 3302aa136b Update README 2019-09-29 20:46:31 +01:00
Joe Rickerby 14d9b4091e Update changelog 2019-09-29 20:46:23 +01:00
Joe Rickerby aeeac6725a Bump version 2019-09-29 20:40:44 +01:00
Joe Rickerby 41b4b092b1 Merge pull request #167 from mayeut/update-openssl
Update openssl patch from 1.0.2s to 1.0.2t on macOS
2019-09-29 20:34:56 +01:00
mayeut 28186bf142 Update openssl patch from 1.0.2s to 1.0.2t on macOS 2019-09-22 14:46:17 +02:00
Joe Rickerby 4e10d9d897 Merge pull request #163 from astrofrog/circleci-verbose
Clean up CircleCI YAML syntax
2019-09-21 16:26:13 +01:00
Yannick Jadoul c963013858 Fixing weird issue with the shebang of pip installed scripts and __PYVENV_LAUNCHER__ 2019-09-11 23:56:27 +02:00
Thomas Robitaille 9470ca623f Use python -m virtualenv on Windows and Linux 2019-09-10 09:40:20 +01:00
Thomas Robitaille 2e3bc016b4 Try and avoid relying on global virtualenv command 2019-09-10 09:40:20 +01:00
Thomas Robitaille d4732130a7 Use unique temporary directory for virtual environment on linux 2019-09-10 09:40:20 +01:00
Thomas Robitaille 853699c265 Fix calls to pip and virtualenv 2019-09-10 09:40:19 +01:00
Thomas Robitaille 40968897a8 Test package in a virtualenv on Linux and Windows 2019-09-10 09:40:19 +01:00
Thomas Robitaille fdc2ba8715 Try and work around the fact we can't source activate 2019-09-10 09:40:19 +01:00
Thomas Robitaille 3ff59eefc6 Fix syntax 2019-09-10 09:40:19 +01:00
Thomas Robitaille e3416abeb9 Use virtual environment for testing on MacOS X 2019-09-10 09:40:18 +01:00
Joe Rickerby 2ab2d079ab Merge pull request #161 from astrofrog/test-extras-require
Add support for specifying test-time dependencies via extras_require
2019-09-09 22:18:33 +01:00
Joe Rickerby 5e529969ea Merge pull request #153 from mayeut/update-python
Update Python from 3.7.2 to 3.7.4 on macOS
2019-09-09 21:48:50 +01:00
Joe Rickerby b7a689e349 Merge pull request #157 from altendky/patch-1
Add Twisted to working examples list
2019-09-09 21:48:30 +01:00
Thomas Robitaille 4f4fed06e0 Added unit test for CIBW_TEST_EXTRAS 2019-09-09 12:49:11 +01:00
Thomas Robitaille 45fcebf9d8 Fix issue on linux 2019-09-09 12:49:05 +01:00
Thomas Robitaille e67b3bc611 Added support for CIBW_TEST_EXTRAS to allow extras_require to be used to install test dependencies 2019-09-09 12:49:04 +01:00
Thomas Robitaille d8456a0ffa Use one-line commands on CircleCI to ensure that command output is shown 2019-09-07 21:55:42 +01:00
Kyle Altendorf 73681d9b24 Add Twisted to working examples list 2019-08-28 23:06:38 -04:00
mayeut 02ed7b2262 Update Python from 3.7.2 to 3.7.4 on macOS 2019-07-27 11:24:47 +02:00
Joe Rickerby ab86b8cd93 Merge pull request #149 from mayeut/update-openssl
Update openssl patch from 1.0.2r to 1.0.2s on macOS
2019-06-24 10:02:41 +01:00
mayeut 3a03df8ec9 Update openssl patch from 1.0.2r to 1.0.2s on macOS 2019-06-23 18:15:46 +02:00
Joe Rickerby 0e78b2b1f5 Merge pull request #147 from cher-nov/V_for_Veyor
Correct spelling: capitalized 'V' in 'AppVeyor'
2019-06-21 08:53:24 +01:00
Joe Rickerby 5b14c8c0ec Merge pull request #148 from delivrance/add-tgcrypto
Add pyrogram/tgcrypto to README.md
2019-06-21 08:51:49 +01:00
Dan 0627bd09d4 Add pyrogram/tgcrypto to README.md 2019-06-14 21:38:38 +02:00
Dmitry D. Chernov a5e64e216c Correct spelling: capitalized 'V' in 'AppVeyor' 2019-06-10 20:27:32 +10:00
Joe Rickerby 23cf50614f Merge pull request #142 from kngwyu/upd-readme
Specify cibuildwheel=0.11 in Azure example
2019-05-29 08:47:04 +01:00
kngwyu 1e08ff03b3 Specify cibuildwheel=0.11 in README example 2019-05-29 15:15:58 +09:00
Joe Rickerby 2216385c0b Update changelog 2019-05-28 19:22:25 +01:00
Joe Rickerby a1fc0cb117 Bump version 2019-05-28 19:17:28 +01:00
Joe Rickerby 430b71c767 Ensure resources are packaged in release tarballs and wheels
Fix #141
2019-05-28 19:17:05 +01:00
Joe Rickerby 14f14a24d3 Add config for universal wheel support so we can post wheels to PyPI too 2019-05-28 10:34:31 +01:00
Joe Rickerby b732026734 Update changelog 2019-05-26 12:53:51 +01:00
Joe Rickerby 0d85db7111 Bump version 2019-05-26 12:48:43 +01:00
Joe Rickerby 477fc7e060 Merge pull request #132 from joerick/azure-windows
Support Windows on Azure Pipelines [continued...]
2019-05-26 11:38:36 +01:00
Joe Rickerby 17566cdee7 Don't expect Python 3.4 wheels on Azure 2019-04-27 12:12:02 +01:00
Joe Rickerby 49bc742add Remove unused imports 2019-04-27 10:23:07 +01:00
Joe Rickerby 4cbb67fac1 Merge remote-tracking branch 'origin/master' into azure-windows 2019-04-27 10:22:00 +01:00
Joe Rickerby 2e3155decf Merge branch 'master' into azure-windows 2019-04-27 10:11:30 +01:00
Joe Rickerby 719352b1d2 Merge pull request #137 from joerick/custom-test-checks
Custom test checks let individual tests assert exactly which wheels they expect to produce
2019-04-25 14:56:28 +01:00
Joe Rickerby f7d93cc9e4 Fix function name 2019-04-23 22:23:54 +01:00
Joe Rickerby 3f5572e956 Make included scripts virtualenv-friendly 2019-04-23 22:17:59 +01:00
Joe Rickerby bab8b6668e Full error output during pytest fails 2019-04-23 22:17:25 +01:00
Joe Rickerby f29697d623 Retain PYTHONPATH if already in env 2019-04-23 22:17:03 +01:00
Joe Rickerby e87032c830 Rework tests check all wheels produced against a reference list
Also, wrap the cibuildwheel call to make building env easier
2019-04-23 22:15:02 +01:00
Joe Rickerby e360a04dc1 Use utils.platform for platform checks 2019-04-22 23:25:14 +01:00
Joe Rickerby 9050137d2b Neaten the environment modification using triple-quotes and dict.update 2019-04-22 23:23:49 +01:00
Joe Rickerby 857aafbd3f Move the pythonpath fiddling to the test runner
instead of including it in every test
2019-04-22 23:13:34 +01:00
Joe Rickerby 0cd3e426bc Minor formatting fixes 2019-04-22 19:05:34 +01:00
Joe Rickerby 8b632bcb6d Skip cleanup if its not needed (when a test is skipped) 2019-04-22 18:55:55 +01:00
Joe Rickerby 364fc5220e another trailing comma 2019-04-22 18:44:09 +01:00
Joe Rickerby 0ed37f268a In general, prefer single quotes 2019-04-22 18:35:57 +01:00
Joe Rickerby f410fbdd03 Remove trailing commas from environment declarations 2019-04-22 18:33:03 +01:00
Joe Rickerby 21fb27faf7 Rework custom test machinery to give the individual tests more control
on how they're run, and combine environment.json and check.py
2019-04-22 18:22:43 +01:00
Yannick Jadoul ac4b62ca07 Update README.md with --print-build-identifiers switch 2019-04-22 16:15:47 +02:00
Yannick Jadoul 3f7a4d753f Skip non-linux builds for 06_docker_images test, now that we have custom checks 2019-04-20 22:12:45 +02:00
Yannick Jadoul 95d2086ced Adding check.py to tests, rather than a simple generic assert on number of wheels 2019-04-20 20:49:56 +02:00
Yannick Jadoul 52e8f41b5c Added --print-build-identifiers command line option 2019-04-20 19:02:35 +02:00
Joe Rickerby 1e2a2e7d4d Revert "Add azure-template.yml for more compact config"
This reverts commit 6377854545.
2019-04-06 18:03:05 +01:00
Joe Rickerby 6377854545 Add azure-template.yml for more compact config 2019-04-06 17:34:36 +01:00
Joe Rickerby be57269d5d Remove 3.4 from the pipelines config because 3.4 isn't supported 2019-04-06 16:23:14 +01:00
Joe Rickerby d5856884a3 README updates 2019-04-06 16:18:26 +01:00
Joe Rickerby c2d3dc3b0f Update README.md
Fix #133. Thanks @zackw for the report!
2019-04-05 21:31:50 +01:00
Joe Rickerby 9116217b60 Update README.md
Readme improvements, adding Azure config and putting services behind disclosure triangles
2019-03-11 22:37:59 +00:00
Joe Rickerby a8f6684bfd Skip Python 3.4 builds on Azure 2019-03-11 19:59:31 +00:00
Joe Rickerby 6852d87d2e Update changelog 2019-03-10 23:37:36 +00:00
Joe Rickerby 054c273997 Bump version 2019-03-10 23:32:06 +00:00
Joe Rickerby 652d094e46 Fix typo 2019-03-10 23:19:22 +00:00
Joe Rickerby 1bfe6d45bd Add auto-detect platform for Azure 2019-03-10 23:07:14 +00:00
Joe Rickerby aefde9535b Add azure-pipelines test run config 2019-03-10 22:50:07 +00:00
Joe Rickerby d46fb62e95 Refactor for code style 2019-03-10 22:41:55 +00:00
Joe Rickerby 87a9d170b0 Merge pull request #131 from mayeut/openssl-1.0.2r
Update openssl patch from 1.0.2q to 1.0.2r on macOS
2019-03-10 22:38:47 +00:00
Joe Rickerby dcce949d3c Vendor appveyor_run_with_cmd, but don't use it on azure pipelines 2019-03-10 22:03:31 +00:00
mayeut 1d3c59d804 Update openssl patch from 1.0.2q to 1.0.2r on macOS 2019-03-10 22:28:43 +01:00
Joe Rickerby 0b791dbea5 Merge pull request #130 from YannickJadoul/macos-python-2.7.16
Updating version of Python 2.7 to 2.7.16 on macOS
2019-03-10 21:26:04 +00:00
Yannick Jadoul 44256e4aa5 Revert "Running 'pip install --upgrade setuptools' with 'sudo' on macOS, fixing #122" (#129)
This reverts commit d79ca07bbb.
2019-03-10 21:25:28 +00:00
Joe Rickerby 243103762b Merge branch 'master' into azure-windows 2019-03-10 20:29:05 +00:00
Yannick Jadoul b579cd5f2a Updating version of Python 2.7 to 2.7.16 on macOS 2019-03-10 21:22:41 +01:00
Joe Rickerby 8523b25a18 Merge pull request #128 from YannickJadoul/fix-bashlex-install-permission
Fixing issue #127 by avoiding bashlex 0.13 in 'install_requires'
2019-03-10 19:52:32 +00:00
Yannick Jadoul 637a251b79 Fixing issue #127 by avoiding bashlex 0.13 in 'install_requires' 2019-03-10 14:57:43 +01:00
Thomas Robitaille ac76af4f75 Support Python location on Windows in Azure Pipelines 2019-02-22 22:19:41 +00:00
Joe Rickerby a6ff864010 Merge pull request #125 from ushuz/patch-1
Add missing date to changelog
2019-02-15 22:28:18 +00:00
John Hu 79f044314b Add missing date to changelog 2019-02-14 11:58:56 +08:00
Joe Rickerby 0c0e21aa83 Update changelog 2019-02-03 21:58:53 +00:00
Joe Rickerby f1bba58f86 Bump version 2019-02-03 21:54:00 +00:00
Joe Rickerby 56218d896c Merge pull request #123 from YannickJadoul/fix-issue-122
Running 'pip install --upgrade setuptools' with 'sudo' on macOS, fixing #122
2019-02-03 21:37:57 +00:00
Yannick Jadoul d79ca07bbb Running 'pip install --upgrade setuptools' with 'sudo' on macOS, fixing #122 2019-01-30 17:36:17 +01:00
Joe Rickerby c6f4f01732 Update README.md
ref #93
2019-01-07 22:17:19 +00:00
mayeut 586b3c7197 Update openssl patch from 1.0.2p to 1.0.2q on macOS 2019-01-07 18:34:46 +01:00
mayeut 0b4475ed07 Update Python from 3.6.7, 3.7.1 to 3.6.8, 3.7.2 on macOS 2019-01-06 23:52:57 +01:00
Yannick Jadoul 38b3b0a3da Merge pull request #114 from YannickJadoul/deterministic-preamble-order
Sorting build options dict items when printing preamble
2018-11-30 16:09:53 +01:00
Yannick Jadoul 5adfce9838 Merge pull request #113 from xanderyzwich/master
Refactoring: remove package_name
2018-11-30 00:03:03 +01:00
Yannick Jadoul bc83839387 Sorting build options dict items when printing preamble 2018-11-30 00:02:18 +01:00
Yannick Jadoul 481b1cb060 Revert "Uninstalling oclint in Travis CI config to fix HomeBrew upgrade of gcc (triggered by upgrading Python)"
This reverts commit c43f1b6e3d.
2018-11-29 23:37:04 +01:00
Yannick Jadoul ccfc3c3aa1 Fixing indentation error, and keeping only check for setup.py in project root directory in __main__.py 2018-11-29 23:26:10 +01:00
unknown 3d23cbf2a6 corrected as per notations from @YannickJadoul on #113 2018-11-29 02:44:19 +00:00
Joe Rickerby b9a296324d Merge pull request #108 from YannickJadoul/py27-popen-args
Fixing "AttributeError: 'Popen' object has no attribute 'args'" on Python 2.7 for Linux builds
2018-11-06 21:22:22 +00:00
Corey McCarty c4822ebdd6 Remove Try/Except for package_name #102
recommended by @YannickJadoul
2018-11-05 16:30:34 -06:00
corey.d.mccarty 2ca6500bba removed '--name' pieces for #102 2018-11-05 11:47:31 -05:00
corey.d.mccarty 8dd71189b2 removed 'package-name' as per #102 2018-11-05 11:16:42 -05:00
Yannick Jadoul a448c02d7f Fixing "AttributeError: 'Popen' object has no attribute 'args'" on Python 2.7 for Linux builds 2018-10-28 11:51:10 +01:00
Yannick Jadoul 696866bfe1 Merge pull request #111 from mayeut/openssl-update
Update openssl patch from 1.0.2o to 1.0.2p on macOS
2018-10-28 11:46:20 +01:00
Yannick Jadoul 1faa2fe5df Merge pull request #110 from mayeut/python-update
Update Python from 3.6.6, 3.7.0 to 3.6.7, 3.7.1 on macOS
2018-10-28 11:46:05 +01:00
Yannick Jadoul 602acebcc8 Merge pull request #112 from YannickJadoul/brew-upgrade-gcc
Fixing Travic CI build with HomeBrew upgrade of gcc
2018-10-28 11:44:38 +01:00
Yannick Jadoul c43f1b6e3d Uninstalling oclint in Travis CI config to fix HomeBrew upgrade of gcc (triggered by upgrading Python) 2018-10-27 19:22:53 +02:00
mayeut 0d3e67b1f9 Update openssl patch from 1.0.2o to 1.0.2p on macOS 2018-10-26 19:25:25 +02:00
mayeut e3b565320c Update Python from 3.6.6, 3.7.0 to 3.6.7, 3.7.1 on macOS 2018-10-26 19:23:49 +02:00
Yannick Jadoul 56973d34df Merge pull request #109 from safijari/add_apriltags2_to_readme
Add apriltags2-ethz library to readme
2018-10-18 11:13:02 +02:00
Jariullah Safi 66e9a1cc19 Update README.md 2018-10-18 00:04:25 -07:00
Joe Rickerby 2a91396064 Bump version 2018-09-23 22:08:39 +01:00
Joe Rickerby 1c98a9ed22 Update changelog 2018-09-23 22:07:47 +01:00
Joe Rickerby dbcf5ef64b Clarify README shared library note 2018-09-23 22:07:36 +01:00
Joe Rickerby cc030312a3 Prepare changelog update 2018-09-23 21:38:36 +01:00
Joe Rickerby 31c162fa59 Remove Python 3.3 support on windows 2018-09-23 21:38:36 +01:00
Joe Rickerby d80636aa22 Merge pull request #101 from YannickJadoul/cibw-build
Adding CIBW_BUILD option
2018-09-23 21:31:42 +01:00
Yannick Jadoul 22a6f0c7a9 Fixing tests by reducing minimum number of built wheels 2018-09-23 13:08:26 +02:00
Yannick Jadoul 7362075b61 Changing variable name of BuildSelector instance, updating Python version in test 04_build_skip, and adding unit tests for BuildSelector 2018-09-23 13:08:26 +02:00
Yannick Jadoul c108807e16 Renaming test 04_skip to 04_build_skip and amending it to test CIBW_BUILD as well 2018-09-23 13:07:28 +02:00
Yannick Jadoul 05a054245a Updating README.md to include CIBW_BUILD and interation with CIBW_SKIP 2018-09-23 13:07:28 +02:00
Yannick Jadoul a5f89fa7aa Adding CIBW_BUILD option and changing util.BuildSkipper to util.BuildSelector 2018-09-23 13:07:28 +02:00
Yannick Jadoul cf73851c61 Merge pull request #97 from YannickJadoul/docker-without-timeout
Reordering the Linux docker commands to get rid of timeout logic
2018-09-23 12:18:32 +02:00
Joe Rickerby 9372e37b18 Merge pull request #95 from anthrotype/overwrite-existing-wheel
overwrite existing wheel file with same name
2018-09-16 19:24:21 +01:00
Joe Rickerby fbb447c3aa Merge pull request #100 from msanders/patch-1
Add AutoPy
2018-09-15 11:08:42 +01:00
Michael Sanders 1e978d1b35 Add AutoPy 2018-09-14 12:36:46 -07:00
Yannick Jadoul 1dbda7af7e Add '--force' to 'docker rm' command in Linux builds 2018-09-12 11:52:41 +02:00
Yannick Jadoul b64770a560 Cleaning up use of run_docker and removing some debug output 2018-09-09 16:11:42 +02:00
Yannick Jadoul 4cc09a35b4 Removing monotonic from dependencies (until necessary again) 2018-09-09 01:24:07 +02:00
Yannick Jadoul d4885fe44a Fixing outdated Python 2 syntax error 2018-09-09 01:24:07 +02:00
Yannick Jadoul fcf1e9cd84 Moving stdin communication with docker to run_docker function 2018-09-09 01:23:48 +02:00
Yannick Jadoul f417a91a57 First try at getting rid of timeout logic in Linux docker handling, by swapping splitting docker run into create and start 2018-09-09 00:53:08 +02:00
Cosimo Lupo 1b9c74aabc macos: no need to call os.remove, shutil.move overwrites on posix 2018-09-08 18:41:39 +01:00
Joe Rickerby 35832c4309 Readme tweaks 2018-09-08 17:13:39 +01:00
Cosimo Lupo c9fffab6ea remove same-named wheel before shutil.move
In https://github.com/adobe-type-tools/afdko/pull/595 we attempt to build a py2.py3 wheel
thus the filename of the wheel is the same as the previous ones, and it causes a shutil.Error
https://travis-ci.org/adobe-type-tools/afdko/jobs/424691105#L1460

just remove the previous existing file before moving the new one (they'll be identical anyway,
or at least they *should*).
2018-09-06 11:34:50 +01:00
Kyle Altendorf 9f7fdbf456 Add CircleCI support (#91)
* Initial guess at supporting CircleCI

joerick/cibuildwheel#90

* Add note about setup_remote_docker on Circle

* Add diagnostic print of entire docker command

* Add more diagnostic prints

* Retrigger for Circle build

* Preliminary .circleci/config.yml

* Add workflows to Circle

* drop osx on circle

* call python3 directly on circle

* drop repeat pip install

* use a virtualenv on circle

* use a virtualenv on circle... again

* use a virtualenv on circle... again... again

* setup_remote_docker on circle

* try to manually copy into docker on circle

* correct Host

* correct docker calls

* refactor docker calls

* take 2 on the docker cp destination

* more docker cp debugging

* more docker cp debugging... again

* docker cp explicitly to /project

* wait until docker container is up

* wait until docker container is up... again

* and copy results back

* and copy results back... again

* create /output in container

* create /output in container... again

* copy contents of container's /output

* Retrigger ci

* fix merge typo

* fix monotonic

* always install monotonic

* always install monotonic... again

* correct to use project_dir

* wait a bit longer and a bit smarter

* wait a bit longer and a bit smarter... again

* add back circle osx

* add back circle osx... again

* py2/3 for circle

* py2/3 for circle... again

* use python2.7 image on circle linux

* (mostly) remove unused ci host identification code

* skip inspecting docker for the container, just retry copy on failure

* cleanup docker container and images

* fully remove ci host detection

* docs and tidy

* add circle badge
2018-09-05 09:15:32 +01:00
Yannick Jadoul 7c6b331e15 Merge pull request #84 from YannickJadoul/unbuffered-output
Applying unbuffered output to all platforms instead of only Windows
2018-09-02 22:49:26 +02:00
Tommy 22f69e4ced Added a repo using cibuildwheel and fixed some spelling (#92)
* Added KDEpy and fixed some spelling

* Reversed spelling, added repo to README

* Fixing single 'progams' typo in README
2018-09-02 22:40:49 +02:00
Joe Rickerby 4083a7600a Merge pull request #88 from miguelsousa/show-err-output
Improve error reporting during package name fetching
2018-08-21 22:52:45 +01:00
Miguel Sousa 20624e44a3 Improve error reporting during package name fetching 2018-08-21 14:11:28 -07:00
Yannick Jadoul 332b8ec6ac Merge pull request #86 from miguelsousa/patch-1
Update README.md
2018-08-20 09:09:51 +02:00
Miguel Sousa eaf59e385c Update README.md
Add horizontal rules between option descriptions; they make it easier to understand what text belongs to each option.
2018-08-19 21:06:43 -07:00
Yannick Jadoul 57454e75b0 Applying unbuffered output to all platforms instead of only Windows 2018-08-02 12:04:39 +02:00
Joe Rickerby 391c95d355 Update README.md 2018-07-29 18:21:19 +01:00
Joe Rickerby 8124b14491 Bump version 2018-07-29 18:19:24 +01:00
Joe Rickerby b3b15f8404 Merge pull request #81 from madig/macos-test-cmd-in-shell
macOS: run test_command in shell
2018-07-29 14:05:57 +01:00
Joe Rickerby 9a96910919 Merge pull request #83 from mayeut/pybase64
Add pybase64 to the list of working examples
2018-07-29 14:01:43 +01:00
mayeut fce00dd77e Add pybase64 to the list of working examples 2018-07-11 00:03:15 +02:00
Joe Rickerby 6da52a544b Bump version 2018-07-10 19:03:48 +01:00
Joe Rickerby c8037fb237 Update changelog 2018-07-10 19:03:38 +01:00
Joe Rickerby 95a81f2216 Merge pull request #82 from mayeut/update-macos-python-3.6
Update Python 3.6 from 3.6.5 to 3.6.6 on macOS
2018-07-10 18:54:50 +01:00
Joe Rickerby 56c9c9864d Merge pull request #76 from jlaine/python37-windows
Build Windows wheels for Python 3.7 (fixes #75)
2018-07-10 18:51:47 +01:00
Joe Rickerby 0789842ef0 Add note about shell use on mac and linux 2018-07-10 18:46:10 +01:00
Joe Rickerby 5c47700d31 Add platform-specific notes to readme 2018-07-10 18:44:27 +01:00
Joe Rickerby 5ef7eeba4d Update readme: add @mayeut to maintainers team! 2018-07-10 18:39:29 +01:00
mayeut bb554acb28 Update Python 3.6 from 3.6.5 to 3.6.6 on macOS 2018-07-07 14:15:45 +02:00
Joe Rickerby ea3c52631f Add platform-specific CIBW_TEST_COMMAND and CIBW_TEST_REQUIRES variants 2018-07-05 09:58:05 +01:00
Joe Rickerby b18281867b Add test for CIBW_TEST_COMMAND running in a shell on mac and linux 2018-07-05 09:28:44 +01:00
Nikolaus Waxweiler 4a0d05df49 macOS: run test_command in shell
Fixes https://github.com/joerick/cibuildwheel/issues/39.
2018-07-04 15:56:12 +01:00
Joe Rickerby c1cd99ee4c Add check for python & pip within the configured python root 2018-07-01 21:38:14 +01:00
Joe Rickerby e68400b403 Update changelog 2018-07-01 21:30:53 +01:00
Jeremy Lainé 2f1f34f693 Build Windows wheels for Python 3.7 (fixes #75) 2018-07-01 22:30:22 +02:00
Joe Rickerby 3ef401b19e Bump version 2018-07-01 21:28:28 +01:00
Joe Rickerby 8800ea514b Merge pull request #79 from YannickJadoul/python-macos-3.7.0
Update Python 3.7.0rc1 to 3.7.0 on macOS
2018-07-01 21:27:00 +01:00
Yannick Jadoul f62b9755e1 Update Python 3.7.0rc1 to 3.7.0 on macOS 2018-06-30 18:28:04 +02:00
Joe Rickerby 033ba29ec6 Update changelog 2018-06-18 23:17:42 +01:00
Joe Rickerby 0627b38402 Bump version 2018-06-18 23:09:19 +01:00
Joe Rickerby 189dc13714 Merge pull request #71 from mayeut/macos-ssl
macOS: patch _ssl module on Python 3.4 & 3.5
2018-06-18 23:02:01 +01:00
Joe Rickerby 793026f3ed Merge pull request #60 from YannickJadoul/python-pip-replacement
Removing replacement of {python} and {pip} in CIBW_BEFORE_BUILD
2018-06-18 22:59:52 +01:00
Joe Rickerby 08b4895b9c Changelog update 2018-06-18 22:57:22 +01:00
Joe Rickerby 7c635b4550 Bump version 2018-06-18 22:52:02 +01:00
Joe Rickerby 33433f0b21 Merge pull request #73 from lelit/py37
Add support for Python 3.7
2018-06-18 22:50:54 +01:00
Joe Rickerby e3981db2a6 Skip the custom docker image specifier for Python 3.7
We'll reenable this when 3.7 is released and dockcross updates :)
2018-06-18 22:35:05 +01:00
Joe Rickerby 1ec652dff8 Fix pip variable use 2018-06-17 21:06:00 +01:00
Joe Rickerby d2394e9a57 Merge commit '57a2259a00bf7ea3309faa231406df8e487ae792' into python-pip-replacement
* commit '57a2259a00bf7ea3309faa231406df8e487ae792':
  Use travis-ci provided python3 on Linux
  linux: transfer ownership of the wheel to the current user
  Update changelog
  Bump version
  macOS/Windows: Update setuptools
  Drop python 3.3 support on Linux
  macOS: update to python 2.7.15
  Renaming util.get_build_verbosity_flag into util.get_build_verbosity_extra_flags
  Bump version
  windows: upgrade pip with 'python -m pip'
  Fixing empty verbosity flag argument to `subprocess.check_call`
  Adding an to make the `pip wheel` invocation more or less verbose
2018-06-17 21:00:16 +01:00
Joe Rickerby 0b21df216e update support matrix in readme 2018-06-17 20:52:46 +01:00
Lele Gaifax e5b9d1f586 Fix mistake in directory name 2018-06-16 15:23:26 +02:00
Lele Gaifax 9b31b5e6c9 Add support for Python 3.7
This enables building binary wheels for Python 3.7, now at its rc1 release.

It is included in the latest manylinux1 Docker image, see https://github.com/pypa/manylinux/pull/196.

Accordingly to https://www.appveyor.com/docs/build-environment/#python it is not yet available on Appveyor.
2018-06-16 13:42:11 +02:00
mayeut 1a910257bb macOS: patch _ssl module on Python 3.4 & 3.5 2018-05-06 17:13:21 +02:00
mayeut 4f542ca3d4 Add test for TLS 1.2 support & valid certificates 2018-05-06 17:13:21 +02:00
Yannick Jadoul 57a2259a00 Merge pull request #66 from mayeut/drop-linux-python3.3
Give ownership of the wheel files to the current user instead of root on Linux
2018-05-06 16:00:42 +02:00
mayeut d186b0bbb7 Use travis-ci provided python3 on Linux 2018-05-06 15:44:27 +02:00
mayeut 57cdb8711c linux: transfer ownership of the wheel to the current user 2018-05-06 15:44:27 +02:00
Joe Rickerby 7448ca3cf1 Update changelog 2018-05-04 10:21:34 -07:00
Joe Rickerby d93547d8be Bump version 2018-05-04 10:04:39 -07:00
Yannick Jadoul a863e21b14 Merge pull request #68 from mayeut/python-update
macOS: update to python 2.7.15
2018-05-04 17:43:36 +02:00
mayeut b4c0150d43 macOS/Windows: Update setuptools 2018-05-04 17:27:33 +02:00
Yannick Jadoul c8019dac1d Merge pull request #67 from mayeut/only-drop-linux-python3.3
Drop python 3.3 support on Linux
2018-05-04 12:12:48 +02:00
mayeut e6fa70a910 Drop python 3.3 support on Linux 2018-05-03 22:05:45 +02:00
mayeut b19e8b76f3 macOS: update to python 2.7.15 2018-05-02 22:01:53 +02:00
Yannick Jadoul 23ab1f780e Merge pull request #61 from YannickJadoul/pip-verbose
Adding an option to make the `pip wheel` invocation more or less verbose
2018-04-30 15:24:19 +02:00
Yannick Jadoul eedcd62753 Renaming util.get_build_verbosity_flag into util.get_build_verbosity_extra_flags 2018-04-30 15:07:56 +02:00
Joe Rickerby 0156a9a870 Fix "'NoneType' is not iterable" error
The build_options dict contains None objects ! :)
2018-04-08 23:38:54 +01:00
Joe Rickerby 460a4d9656 Code tidy/reorganise 2018-04-08 23:26:04 +01:00
Yannick Jadoul 8d9d970874 Fixing empty verbosity flag argument to subprocess.check_call 2018-04-08 21:51:19 +02:00
Yannick Jadoul c563bca054 Adding an to make the pip wheel invocation more or less verbose 2018-04-08 21:37:40 +02:00
Joe Rickerby b47a5c018f Remove unused warnings import 2018-04-08 19:11:38 +01:00
Joe Rickerby 94e33cd7e3 Switch to a more user-friendly warning style 2018-04-08 18:42:47 +01:00
Joe Rickerby c9c54602ed Correct comment 2018-04-08 18:42:21 +01:00
Joe Rickerby b74333a940 Simplify prepare_command function and add deprecation warning 2018-04-08 18:25:18 +01:00
Joe Rickerby 4655311a7a Merge origin/master into python-pip-replacement
* commit '71503b7143d22765a8f2b324dd75046644ea5726':
  Replacing leftover `test_command.format(...)` by `prepare_command(test_command, ...)` in linux.py
  Replacing {python} and {pip} in CIBW_TEST_COMMAND (and {project} in CIBW_BEFORE_BUILD) for consistency

# Conflicts:
#	README.md
#	cibuildwheel/macos.py
2018-04-08 18:11:00 +01:00
Joe Rickerby 5099d60584 Use a separate folder for bin overrides 2018-04-08 18:05:59 +01:00
Yannick Jadoul 2ebde4c078 Reverting removal of prepare_command to maintain backwards compatibility of configurations with {python} and {pip} 2018-04-08 17:01:54 +02:00
Yannick Jadoul 4d61b08fa3 Updating README, removing documentation on {python} and {pip} 2018-04-08 15:26:09 +02:00
Yannick Jadoul 5e009e53c9 Symlinking only on first-time installation of Python versions on mac OS X 2018-04-08 15:15:47 +02:00
Yannick Jadoul 783a4deec6 Symlinking python3 and pip3 to python and pip for OS X runs 2018-04-08 15:05:21 +02:00
Yannick Jadoul 529e22bfe0 Removing {python} from test 03_before_build 2018-04-08 14:14:01 +02:00
Yannick Jadoul 418cb9c39d Removing replacement of {python} and {pip} in CIBW_BEFORE_BUILD 2018-04-08 13:40:30 +02:00
71 changed files with 2891 additions and 702 deletions
+73
View File
@@ -0,0 +1,73 @@
version: 2
jobs:
osx-python2:
macos:
xcode: "10.0.0"
environment:
PYTHON: python2
steps:
- checkout
- run:
name: Prepare the environment.
command: bash .circleci/prepare.sh
- run:
name: Test.
command: venv/bin/python ./bin/run_tests.py
osx-python3:
macos:
xcode: "10.0.0"
environment:
PYTHON: python3
steps:
- checkout
- run:
name: Prepare the environment.
command: bash .circleci/prepare.sh
- run:
name: Test.
command: venv/bin/python ./bin/run_tests.py
linux-python2:
docker:
- image: circleci/python:2.7
environment:
PYTHON: python2
steps:
- checkout
- setup_remote_docker
- run:
name: Prepare the environment.
command: bash .circleci/prepare.sh
- run:
name: Test.
command: venv/bin/python ./bin/run_tests.py
linux-python3:
docker:
- image: circleci/python:3.6
environment:
PYTHON: python3
steps:
- checkout
- setup_remote_docker
- run:
name: Prepare the environment.
command: bash .circleci/prepare.sh
- run:
name: Test.
command: venv/bin/python ./bin/run_tests.py
workflows:
version: 2
all-tests:
jobs:
- osx-python2
- osx-python3
- linux-python2
- linux-python3
+7
View File
@@ -0,0 +1,7 @@
$PYTHON --version
$PYTHON -m pip --version
$PYTHON -m pip install -q --user --ignore-installed --upgrade virtualenv
$PYTHON -m virtualenv -p $PYTHON venv
venv/bin/python -m pip install -r requirements-dev.txt
venv/bin/python -m pip freeze
venv/bin/python --version
+11
View File
@@ -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
+19 -31
View File
@@ -5,42 +5,30 @@ matrix:
# Linux Python 2
- sudo: required
language: python
services:
- docker
env:
- "PYTHON=python2"
python: 2.7
services: docker
env: PYTHON=python
# Linux Python 3
- sudo: required
language: python
services:
- docker
env:
- "PYTHON=python3"
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y python3-pip
# macOS Python 2
- os: osx
env:
- "PYTHON=python2"
python: 3.5
services: docker
env: PYTHON=python
# macOS Python 3
- os: osx
env:
- "PYTHON=python3"
before_install:
- brew update
- brew outdated python || brew upgrade python
env: PYTHON=python3
script:
- |
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
$PYTHON -m pip install -r requirements-dev.txt
$PYTHON ./bin/run_tests.py
else
# linux test requires root to clean up the wheelhouse (docker runs as root)
sudo $PYTHON -m pip install -r requirements-dev.txt
sudo $PYTHON ./bin/run_tests.py
fi
- os: windows
language: shell
before_install:
- choco install python3 --version 3.5.4 --no-progress -y
install:
- C:\\Python35\\python -m pip install -r requirements-dev.txt
script:
- C:\\Python35\\python ./bin/run_tests.py
install: $PYTHON -m pip install -r requirements-dev.txt
script: $PYTHON ./bin/run_tests.py
+1 -1
View File
@@ -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:
+262 -310
View File
@@ -1,420 +1,372 @@
cibuildwheel
============
[![PyPI](https://img.shields.io/pypi/v/cibuildwheel.svg)](https://pypi.python.org/pypi/cibuildwheel) [![Build Status](https://travis-ci.org/joerick/cibuildwheel.svg?branch=master)](https://travis-ci.org/joerick/cibuildwheel) [![Build status](https://ci.appveyor.com/api/projects/status/wbsgxshp05tt1tif/branch/master?svg=true)](https://ci.appveyor.com/project/joerick/cibuildwheel/branch/master)
[![PyPI](https://img.shields.io/pypi/v/cibuildwheel.svg)](https://pypi.python.org/pypi/cibuildwheel) [![Documentation Status](https://readthedocs.org/projects/cibuildwheel/badge/?version=stable)](https://cibuildwheel.readthedocs.io/en/stable/?badge=stable) [![Build Status](https://travis-ci.org/joerick/cibuildwheel.svg?branch=master)](https://travis-ci.org/joerick/cibuildwheel) [![Build status](https://ci.appveyor.com/api/projects/status/wbsgxshp05tt1tif/branch/master?svg=true)](https://ci.appveyor.com/project/joerick/cibuildwheel/branch/master) [![CircleCI](https://circleci.com/gh/joerick/cibuildwheel.svg?style=svg)](https://circleci.com/gh/joerick/cibuildwheel) [![Build Status](https://dev.azure.com/joerick0429/cibuildwheel/_apis/build/status/joerick.cibuildwheel?branchName=master)](https://dev.azure.com/joerick0429/cibuildwheel/_build/latest?definitionId=2&branchName=master)
[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 Travis CI and Appveyor - 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.3 | | ✅ | ✅ | ✅ | ✅ |
| Python 3.4 | ✅ | | ✅ | ✅ | ✅ |
| Python 3.5 | ✅ | | ✅ | ✅ | ✅ |
| Python 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ |
| | 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 | | ✅ | ✅ | ✅ | ✅ | ✅ |
- Builds manylinux, macOS and Windows (32 and 64bit) wheels using Travis CI and Appveyor
> ¹ Not supported on Travis
- 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 on **Travis CI** to build Linux and Mac wheels, and **Appveyor** to build Windows wheels.
`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** Linux and Windows are supported.
`cibuildwheel` is not intended to run on your development machine. It will try to install packages globally; this is no good. Travis CI and Appveyor run their builds in isolated environments, so are ideal for this kind of script.
| | Linux | macOS | Windows |
|-----------------|-------|-------|---------|
| Azure Pipelines | ✅ | ✅ | ✅ |
| Travis CI | ✅ | ✅ | ✅ |
| AppVeyor | ✅ | | ✅ |
| CircleCI | ✅ | ✅ | |
### Minimal setup
`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.
- Create a `.travis.yml` file in your repo.
<!--intro-end-->
```
language: python
matrix:
include:
- sudo: required
services:
- docker
env: PIP=pip
- os: osx
language: generic
env: PIP=pip2
Example setup
-------------
script:
- $PIP install cibuildwheel==0.7.2
- cibuildwheel --output-dir wheelhouse
```
To build manylinux, macOS, and Windows wheels on Travis CI and upload them to PyPI whenever you tag a version, you could use this `.travis.yml`:
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.
```yaml
language: python
- Create an `appveyor.yml` file in your repo.
jobs:
include:
# perform a linux build
- services: docker
# and a mac build
- os: osx
language: shell
# and a windows build
- os: windows
language: shell
before_install:
- choco install python --version 3.8.0
- export PATH="/c/Python38:/c/Python38/Scripts:$PATH"
```
build_script:
- pip install cibuildwheel==0.7.2
- 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.
- Commit those files, enable building of your repo on Travis CI and Appveyor, and push.
env:
global:
- TWINE_USERNAME=joerick
# Note: TWINE_PASSWORD is set in Travis settings
All being well, you should get wheels delivered to you in a few minutes.
install:
- python -m pip install twine cibuildwheel==1.1.0
> ⚠️ Got an error? Check the [checklist](#it-didnt-work) below.
script:
# build the wheels, put them into './wheelhouse'
- python -m cibuildwheel --output-dir wheelhouse
### 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_SKIP` | Skip certain Python versions |
| **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:
- Progams 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.
- 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.
after_success:
# if the release was tagged, upload them to PyPI
- if [[ $TRAVIS_TAG ]]; then python -m twine upload wheelhouse/*.whl; fi
```
For more information, including how to build on Appveyor, Azure, CircleCI, check out the [documentation](https://cibuildwheel.readthedocs.org) and also check out [the examples](https://github.com/joerick/cibuildwheel/tree/master/examples).
Options
-------
```
usage: cibuildwheel [-h]
[--output-dir OUTPUT_DIR]
[--platform PLATFORM]
[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.
```
Most of the config is via environment variables. These go into `.travis.yml` and `appveyor.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`.
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 variable: `CIBW_SKIP`
| ---
Optional.
Space-separated list of builds to skip. Each build has an identifier like `cp27-manylinux1_x86_64` or `cp34-macosx_10_6_intel` - you can list ones to skip here and `cibuildwheel` won't try to build them.
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`
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:
- Skip building on Python 2.7 on the Mac: `cp27-macosx_10_6_intel`
- Skip building on Python 2.7 on all platforms: `cp27-*`
- Skip Python 2.7 on Windows: `cp27-win*`
- Skip Python 2.7 on 32bit Windows: `cp27-win32`
- Skip Python 3.4 and Python 3.5: `cp34-* cp35-*`
- Skip Python 3.6 on Linux: `cp36-manylinux*`
- Only build on Python 3.6: `cp27-* cp34-* cp35-*`
| 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}`. These are useful when you need to write `python3` or `pip3` on a Python 3.x build. `{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. Just like in the `CIBW_BEFORE_BUILD` option, `{python}`, `{pip}`, and `{project}` will respectively be replaced by the Python executable, the pip executable, and the absolute project directory.
Example: `nosetests {project}/tests`
| 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`
--
#### 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` or `appveyor.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.
| | 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_REPAIR_WHEEL_COMMAND`](https://cibuildwheel.readthedocs.io/en/stable/options/#repair-wheel-command) | Execute a shell command to repair each (non-pure Python) built wheel |
| | [`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 each built wheel |
| | [`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)
- [Parselmouth](https://github.com/YannickJadoul/Parselmouth)
- [python-admesh](https://github.com/admesh/python-admesh)
- [pybase64](https://github.com/mayeut/pybase64)
- [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 will automatically bundle library dependencies. This is similar to static linking, so it might have some licence implications. Check the license for any code you're pulling in to make sure that's allowed.
Since `cibuildwheel` repairs the wheel with `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.
This is similar to static linking, so it might have some licence implications. Check the license for any code you're pulling in to make sure that's allowed.
Changelog
=========
### 1.1.0
_7 December 2019_
- ✨ Add support for building manylinux2014 wheels. To use, set
`CIBW_MANYLINUX_X86_64_IMAGE` and CIBW_MANYLINUX_I686_IMAGE to
`manylinux2014`.
- ✨ Add support for [Linux on Appveyor](https://www.appveyor.com/blog/2018/03/06/appveyor-for-linux/) (#204, #207)
- ✨ Add `CIBW_REPAIR_WHEEL_COMMAND` env variable, for changing how
`auditwheel` or `delocate` are invoked, or testing an equivalent on
Windows. (#211)
- 📚 Added some travis example configs - these are available in /examples. (#228)
### 1.0.0
_10 November 2019_
- ✨ Add support for building Python 3.8 wheels! (#180)
- ✨ Add support for building manylinux2010 wheels. cibuildwheel will now
build using the manylinux2010 images by default. If your project is still
manylinux1 compatible, you should get both manylinux1 and manylinux2010
wheels - you can upload both to PyPI. If you always require manylinux1 wheels, you can
build using the old manylinux1 image using the [manylinux image](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) option.
(#155)
- 📚 Documentation is now on its [own mini-site](https://cibuildwheel.readthedocs.io),
rather than on the README (#169)
- ✨ Add support for building Windows wheels on Travis CI. (#160)
- 🛠 If you set `CIBW_TEST_COMMAND`, your tests now run in a virtualenv. (#164)
- 🛠 Windows now uses Python as installed by nuget, rather than the versions
installed by the various CI providers. (#180)
- 🛠 Update Python from 2.7.16 to 2.7.17 and 3.7.4 to 3.7.5 on macOS (#171)
- ⚠️ Removed support for Python 3.4 (#168)
### 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
[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
can more precisely assert what should be produced for each one. (#136, #137).
### 0.10.2
_10 March 2019_
- 🛠 Revert temporary fix in macOS, that was working around a bug in pip 19 (#129)
- 🛠 Update Python to 2.7.16 on macOS
- 🛠 Update OpenSSL patch to 1.0.2r on macOS
### 0.10.1
_3 February 2019_
- 🐛 Fix build stalling on macOS (that was introduced in pip 19) (#122)
- 🐛 Fix "AttributeError: 'Popen' object has no attribute 'args'" on Python 2.7 for Linux builds (#108)
- 🛠 Update Python from 3.6.7, 3.7.1 to 3.6.8, 3.7.2 on macOS
- 🛠 Update openssl patch from 1.0.2p to 1.0.2q on macOS
- 🛠 Sorting build options dict items when printing preamble (#114)
### 0.10.0
_23 September 2018_
- ✨ Add `CIBW_BUILD` option, for specifying which specific builds to perform (#101)
- ✨ Add support for building Mac and Linux on CircleCI (#91, #97)
- 🛠 Improved support for building universal wheels (#95)
- 🛠 Ensure log output is unbuffered and therefore in the correct order (#92)
- 🛠 Improved error reporting for errors that occur inside a package's setup.py (#88)
- ⚠️ Removed support for Python 3.3 on Windows.
### 0.9.4
_29 July 2018_
- 🛠 CIBW_TEST_COMMAND now runs in a shell on Mac (as well as Linux) (#81)
### 0.9.3
_10 July 2018_
- 🛠 Update to Python 3.6.6 on macOS (#82)
- ✨ Add support for building Python 3.7 wheels on Windows (#76)
- ⚠️ Deprecated support for Python 3.3 on Windows.
### 0.9.2
_1 July 2018_
- 🛠 Update Python 3.7.0rc1 to 3.7.0 on macOS (#79)
### 0.9.1
_18 June 2018_
- 🛠 Removed the need to use `{python}` and `{pip}` in `CIBW_BEFORE_BUILD` statements, by ensuring the correct version is always on the path at `python` and `pip` instead. (#60)
- 🛠 We now patch the _ssl module on Python 3.4 and 3.5 so these versions can still make SSL web requests using TLS 1.2 while building. (#71)
### 0.9.0
_18 June 2018_
- ✨ Add support for Python 3.7 (#73)
### 0.8.0
_4 May 2018_
- ⚠️ Drop support for Python 3.3 on Linux (#67)
- 🐛 Fix TLS by updating setuptools (#69)
### 0.7.1
- macOS: Fix Pip bugs resulting from PyPI TLS 1.2 enforcement
- macOS: Fix brew Python3 version problems in the CI
_2 April 2017_
- 🐛 macOS: Fix Pip bugs resulting from PyPI TLS 1.2 enforcement
- 🐛 macOS: Fix brew Python3 version problems in the CI
### 0.7.0
- You can now specify a custom docker image using the `CIBW_MANYLINUX1_X86_64_IMAGE` and `CIBW_MANYLINUX1_I686_IMAGE` options. (#46)
- Fixed a bug where cibuildwheel would download and build a package from PyPI(!) instead of building the package on the local machine. (#51)
_7 January 2018_
- ✨ You can now specify a custom docker image using the `CIBW_MANYLINUX1_X86_64_IMAGE` and `CIBW_MANYLINUX1_I686_IMAGE` options. (#46)
- 🐛 Fixed a bug where cibuildwheel would download and build a package from PyPI(!) instead of building the package on the local machine. (#51)
### 0.6.0
- On the Linux build, the host filesystem is now accessible via `/host` (#36)
- Fixed a bug where setup.py scripts would run the wrong version of Python when running subprocesses on Linux (#35)
_9 October 2017_
- ✨ On the Linux build, the host filesystem is now accessible via `/host` (#36)
- 🐛 Fixed a bug where setup.py scripts would run the wrong version of Python when running subprocesses on Linux (#35)
### 0.5.1
- Fixed a couple of bugs on Python 3.
- Added experimental support for Mac builds on [Bitrise.io](https://www.bitrise.io)
_10 September 2017_
- 🐛 Fixed a couple of bugs on Python 3.
- ✨ Added experimental support for Mac builds on [Bitrise.io](https://www.bitrise.io)
### 0.5.0
- `CIBW_ENVIRONMENT` added. You can now set environment variables for each build, even within the Docker container on Linux. This is a big one! (#21)
- `CIBW_BEFORE_BUILD` now runs in a system shell on all platforms. You can now do things like `CIBW_BEFORE_BUILD="cmd1 && cmd2"`. (#32)
_7 September 2017_
-`CIBW_ENVIRONMENT` added. You can now set environment variables for each build, even within the Docker container on Linux. This is a big one! (#21)
-`CIBW_BEFORE_BUILD` now runs in a system shell on all platforms. You can now do things like `CIBW_BEFORE_BUILD="cmd1 && cmd2"`. (#32)
### 0.4.1
- 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!)
_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!)
### 0.4.0
- Fixed a bug that was increasing the build time by building the wheel twice. This was a problem for large projects that have a long build time. If you're upgrading and you need the old behaviour, use `CIBW_BEFORE_BUILD={pip} install .`, or install exactly the dependencies you need in `CIBW_BEFORE_BUILD`. See #18.
_23 July 2017_
- 🐛 Fixed a bug that was increasing the build time by building the wheel twice. This was a problem for large projects that have a long build time. If you're upgrading and you need the old behaviour, use `CIBW_BEFORE_BUILD={pip} install .`, or install exactly the dependencies you need in `CIBW_BEFORE_BUILD`. See #18.
### 0.3.0
- Removed Python 2.6 support on Linux (#12)
_27 June 2017_
- ⚠️ Removed Python 2.6 support on Linux (#12)
### 0.2.1
11 June 2017
_11 June 2017_
- Changed the build process to install the package before building the wheel - this allows direct dependencies to be installed first (#9, thanks @tgarc!)
- Added Python 3 support for the main process, for systems where Python 3 is the default (#8, thanks @tgarc).
- 🛠 Changed the build process to install the package before building the wheel - this allows direct dependencies to be installed first (#9, thanks @tgarc!)
- Added Python 3 support for the main process, for systems where Python 3 is the default (#8, thanks @tgarc).
### 0.2.0
13 April 2017
_13 April 2017_
- 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
- 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
31 March 2017
_31 March 2017_
- First public release!
- 🌟 First public release!
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
-----------
- Joe Rickerby [@joerick](https://github.com/joerick)
- Tomas Garcia [@tgarc](https://github.com/tgarc)
- Yannick Jadoul [@YannickJadoul](https://github.com/YannickJadoul)
- Matthieu Darbois [@mayeut](https://github.com/mayeut)
Credits
-------
`cibuildwheel` stands on the shoulders of giants. Massive props to-
`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)
- @ogrisel for [wheelhouse-uploader](https://github.com/ogrisel/wheelhouse-uploader) and `run_with_env.cmd`
Massive props also to-
- @zfrenchee for [help debugging many issues](https://github.com/joerick/cibuildwheel/issues/2)
- @lelit for some great bug reports and [contributions](https://github.com/joerick/cibuildwheel/pull/73)
- @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.
If `cibuildwheel` is too limited for your needs, consider [matthew-brett/multibuild](http://github.com/matthew-brett/multibuild). `multibuild` is a toolbox for building a wheel on various platforms. It can do a lot more than this project - it's used to build SciPy!
+8 -7
View File
@@ -1,10 +1,11 @@
environment:
matrix:
- PYTHON: "C:\\Python27\\python.exe"
- PYTHON: "C:\\Python35\\python.exe"
image:
- Ubuntu
- Visual Studio 2015
build_script:
- "%PYTHON% -m pip install -r requirements-dev.txt"
# the '-u' flag is required so the output is in the correct order.
- cmd: "C:\\Python27\\python.exe -m pip install -r requirements-dev.txt"
- sh: "${HOME}/.localpython3.7.4/bin/python3 -m pip install -r requirements-dev.txt"
# the '-u' flag is required so the output is in the correct order.
# See https://github.com/joerick/cibuildwheel/pull/24 for more info.
- "%PYTHON% -u ./bin/run_tests.py"
- cmd: "C:\\Python27\\python.exe -u ./bin/run_tests.py"
- sh: "${HOME}/.localpython3.7.4/bin/python3 ./bin/run_tests.py"
+33
View File
@@ -0,0 +1,33 @@
jobs:
- job: linux
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:
- 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: '3.8'
- script: choco install vcpython27 -f -y
displayName: Install Visual C++ for Python 2.7
- bash: |
python -m pip install -r requirements-dev.txt
python ./bin/run_tests.py
+8 -26
View File
@@ -1,31 +1,15 @@
#!/usr/bin/python
#!/usr/bin/env python
from __future__ import print_function
import os, sys, subprocess, shutil, json
from glob import glob
import os, sys, subprocess, shutil
def single_run(test_project):
# load project settings into environment
env_file = os.path.join(test_project, 'environment.json')
project_env = {}
if os.path.exists(env_file):
with open(env_file) as f:
project_env = json.load(f)
# run the test
subprocess.check_call(
[sys.executable, '-m', 'pytest', '-vv', os.path.join(test_project, 'cibuildwheel_test.py')],
)
# run the build
env = os.environ.copy()
project_env = {str(k): str(v) for k, v in project_env.items()} # unicode not allowed in env
env.update(project_env)
print('Building %s with environment %s' % (test_project, project_env))
subprocess.check_call([sys.executable, '-m', 'cibuildwheel', test_project], env=env)
wheels = glob('wheelhouse/*.whl')
print('%s built successfully. %i wheels built.' % (test_project, len(wheels)))
# check some wheels were actually built
assert len(wheels) >= 4
# clean up
shutil.rmtree('wheelhouse')
if __name__ == '__main__':
import argparse
@@ -35,11 +19,9 @@ if __name__ == '__main__':
args = parser.parse_args()
project_path = os.path.abspath(args.test_project_dir)
if not os.path.exists(project_path):
print('No test project not found.', file=sys.stderr)
exit(2)
single_run(project_path)
print('Project built successfully.')
+2 -2
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/env python
from __future__ import print_function
import os, sys, subprocess, shutil, json
@@ -14,7 +14,7 @@ if __name__ == '__main__':
### run the integration tests
test_projects = glob('test/??_*')
test_projects = sorted(glob('test/??_*'))
if len(test_projects) == 0:
print('No test projects found. Aborting.', file=sys.stderr)
+1 -1
View File
@@ -1 +1 @@
__version__ = '0.7.2'
__version__ = '1.1.0'
+138 -46
View File
@@ -4,9 +4,9 @@ import argparse, os, subprocess, sys, textwrap
import cibuildwheel
import cibuildwheel.linux, cibuildwheel.windows, cibuildwheel.macos
from cibuildwheel.environment import parse_environment, EnvironmentParseError
from cibuildwheel.util import BuildSkipper
from cibuildwheel.util import BuildSelector, Unbuffered
def get_option_from_environment(option_name, platform=None):
def get_option_from_environment(option_name, platform=None, default=None):
'''
Returns an option from the environment, optionally scoped by the platform.
@@ -21,7 +21,13 @@ def get_option_from_environment(option_name, platform=None):
if option is not None:
return option
return os.environ.get(option_name)
return os.environ.get(option_name, default)
def strtobool(val):
if val.lower() in ('y', 'yes', 't', 'true', 'on', '1'):
return True
return False
def main():
@@ -38,7 +44,7 @@ def main():
'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]. Default: auto.'))
'Python. Default: auto.'))
parser.add_argument('--output-dir',
default=os.environ.get('CIBW_OUTPUT_DIR', 'wheelhouse'),
help='Destination folder for the wheels.')
@@ -48,34 +54,62 @@ def main():
help=('Path to the project that you want wheels for. Default: the current '
'directory.'))
parser.add_argument('--print-build-identifiers',
action='store_true',
help='Print the build identifiers matched by the current invocation and exit.')
args = parser.parse_args()
detect_obsolete_options()
if args.platform != 'auto':
platform = args.platform
else:
if os.environ.get('TRAVIS_OS_NAME') == 'linux':
platform = 'linux'
elif os.environ.get('TRAVIS_OS_NAME') == 'osx':
platform = 'macos'
elif 'APPVEYOR' in os.environ:
platform = 'windows'
elif 'BITRISE_BUILD_NUMBER' in os.environ:
platform = 'macos'
else:
ci = strtobool(os.environ.get('CI', 'false')) or 'BITRISE_BUILD_NUMBER' in os.environ or 'AZURE_HTTP_USER_AGENT' in os.environ
if not ci:
print('cibuildwheel: Unable to detect platform. cibuildwheel should run on your CI server, '
'Travis CI and Appveyor are supported. You can run on your development '
'machine using the --platform argument. Check --help output for more '
'information.',
'Travis CI, AppVeyor, Azure Pipelines and CircleCI are supported. You can run on your '
'development machine or other CI providers using the --platform argument. Check --help '
'output for more information.',
file=sys.stderr)
exit(2)
if sys.platform.startswith('linux'):
platform = 'linux'
elif sys.platform == 'darwin':
platform = 'macos'
elif sys.platform == 'win32':
platform = 'windows'
else:
print('cibuildwheel: Unable to detect platform from "sys.platform" in a CI environment. You can run '
'cibuildwheel using the --platform argument. Check --help output for more information.',
file=sys.stderr)
exit(2)
output_dir = args.output_dir
test_command = os.environ.get('CIBW_TEST_COMMAND', None)
test_requires = os.environ.get('CIBW_TEST_REQUIRES', '').split()
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)
skip_config = os.environ.get('CIBW_SKIP', '')
environment_config = get_option_from_environment('CIBW_ENVIRONMENT', platform=platform) or ''
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', '')
if platform == 'linux':
repair_command_default = 'auditwheel repair -w {dest_dir} {wheel}'
elif platform == 'macos':
repair_command_default = 'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}'
else:
repair_command_default = ''
repair_command = get_option_from_environment('CIBW_REPAIR_WHEEL_COMMAND', platform=platform, default=repair_command_default)
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:
build_verbosity = 0
try:
environment = parse_environment(environment_config)
@@ -85,55 +119,56 @@ def main():
traceback.print_exc(None, sys.stderr)
exit(2)
skip = BuildSkipper(skip_config)
build_selector = BuildSelector(build_config, skip_config)
# Add CIBUILDWHEEL environment variable
# This needs to be passed on to the docker container in linux.py
os.environ['CIBUILDWHEEL'] = '1'
try:
project_setup_py = os.path.join(project_dir, 'setup.py')
name_output = subprocess.check_output([sys.executable, project_setup_py, '--name'],
universal_newlines=True)
# the last line of output is the name
package_name = name_output.strip().splitlines()[-1]
except subprocess.CalledProcessError as err:
if not os.path.exists(project_setup_py):
print('cibuildwheel: Could not find setup.py at root of project', file=sys.stderr)
exit(2)
else:
print('cibuildwheel: Failed to get name of the package. Command was %s' % err.cmd,
file=sys.stderr)
exit(2)
if package_name == '' or package_name == 'UNKNOWN':
print('cibuildwheel: Invalid package name "%s". Check your setup.py' % package_name,
file=sys.stderr)
if not os.path.exists(os.path.join(project_dir, 'setup.py')):
print('cibuildwheel: Could not find setup.py at root of project', file=sys.stderr)
exit(2)
if args.print_build_identifiers:
print_build_identifiers(platform, build_selector)
exit(0)
build_options = dict(
project_dir=project_dir,
package_name=package_name,
output_dir=output_dir,
test_command=test_command,
test_requires=test_requires,
test_extras=test_extras,
before_build=before_build,
skip=skip,
build_verbosity=build_verbosity,
build_selector=build_selector,
repair_command=repair_command,
environment=environment,
)
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',
'manylinux2014': 'quay.io/pypa/manylinux2014_x86_64'}
default_manylinux_images_i686 = {'manylinux1': 'quay.io/pypa/manylinux1_i686',
'manylinux2010': 'quay.io/pypa/manylinux2010_i686',
'manylinux2014': 'quay.io/pypa/manylinux2014_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
elif platform == 'windows':
pass
# Python is buffering by default when running on the CI platforms, giving problems interleaving subprocess call output with unflushed calls to 'print'
sys.stdout = Unbuffered(sys.stdout)
print_preamble(platform, build_options)
if not os.path.exists(output_dir):
@@ -146,7 +181,29 @@ def main():
elif platform == 'macos':
cibuildwheel.macos.build(**build_options)
else:
raise Exception('Unsupported platform')
print('cibuildwheel: Unsupported platform: {}'.format(platform), file=sys.stderr)
exit(2)
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('''
@@ -161,10 +218,45 @@ def print_preamble(platform, build_options):
print('Build options:')
print(' platform: %r' % platform)
for option, value in build_options.items():
for option, value in sorted(build_options.items()):
print(' %s: %r' % (option, value))
warnings = detect_warnings(platform, build_options)
if warnings:
print('\nWarnings:')
for warning in warnings:
print(' ' + warning)
print('\nHere we go!\n')
def print_build_identifiers(platform, build_selector):
if platform == 'linux':
python_configurations = cibuildwheel.linux.get_python_configurations(build_selector)
elif platform == 'windows':
python_configurations = cibuildwheel.windows.get_python_configurations(build_selector)
elif platform == 'macos':
python_configurations = cibuildwheel.macos.get_python_configurations(build_selector)
else:
python_configurations = []
for config in python_configurations:
print(config.identifier)
def detect_warnings(platform, build_options):
warnings = []
# warn about deprecated {python} and {pip}
for option_name in ['test_command', 'before_build']:
option_value = build_options.get(option_name)
if option_value:
if '{python}' in option_value or '{pip}' in option_value:
warnings.append(option_name + ": '{python}' and '{pip}' are no longer needed, and will be removed in a future release. Simply use 'python' or 'pip' instead.")
return warnings
if __name__ == '__main__':
main()
+119 -74
View File
@@ -1,7 +1,7 @@
from __future__ import print_function
import os, subprocess, sys
import os, subprocess, sys, uuid
from collections import namedtuple
from .util import prepare_command
from .util import prepare_command, get_build_verbosity_extra_flags
try:
from shlex import quote as shlex_quote
@@ -9,37 +9,41 @@ except ImportError:
from pipes import quote as shlex_quote
def build(project_dir, package_name, output_dir, test_command, test_requires, before_build, skip, environment, manylinux1_images):
def get_python_configurations(build_selector):
PythonConfiguration = namedtuple('PythonConfiguration', ['identifier', 'path'])
python_configurations = [
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, test_extras, before_build, build_verbosity, build_selector, repair_command, environment, manylinux_images):
try:
subprocess.check_call(['docker', '--version'])
except:
print('cibuildwheel: Docker not found. Docker is required to run Linux builds. '
'If you\'re building on Travis CI, add `services: [docker]` to your .travis.yml.',
'If you\'re building on Travis CI, add `services: [docker]` to your .travis.yml.'
'If you\'re building on Circle CI in Linux, add a `setup_remote_docker` step to your .circleci/config.yml',
file=sys.stderr)
exit(2)
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='cp33-manylinux1_x86_64', path='/opt/python/cp33-cp33m'),
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='cp27-manylinux1_i686', path='/opt/python/cp27-cp27m'),
PythonConfiguration(identifier='cp27-manylinux1_i686', path='/opt/python/cp27-cp27mu'),
PythonConfiguration(identifier='cp33-manylinux1_i686', path='/opt/python/cp33-cp33m'),
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'),
]
# skip builds as required
python_configurations = [c for c in python_configurations if not skip(c.identifier)]
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:
@@ -50,86 +54,127 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
bash_script = '''
set -o errexit
set -o xtrace
mkdir /output
cd /project
{environment_exports}
for PYBIN in {pybin_paths}; do
# Setup
rm -rf /tmp/built_wheel
rm -rf /tmp/delocated_wheel
mkdir /tmp/built_wheel
mkdir /tmp/delocated_wheel
if [ ! -z {before_build} ]; then
PATH="$PYBIN:$PATH" sh -c {before_build}
fi
# Build that wheel
PATH="$PYBIN:$PATH" "$PYBIN/pip" wheel . -w /tmp/built_wheel --no-deps
# Build the wheel
rm -rf /tmp/built_wheel
mkdir /tmp/built_wheel
PATH="$PYBIN:$PATH" "$PYBIN/pip" wheel . -w /tmp/built_wheel --no-deps {build_verbosity_flag}
built_wheel=(/tmp/built_wheel/*.whl)
# Delocate the wheel
# repair the wheel
rm -rf /tmp/repaired_wheels
mkdir /tmp/repaired_wheels
# NOTE: 'built_wheel' here is a bash array of glob matches; "$built_wheel" returns
# the first element
if [[ "$built_wheel" == *none-any.whl ]]; then
# pure python wheel - just copy
mv "$built_wheel" /tmp/delocated_wheel
if [[ "$built_wheel" == *none-any.whl ]] || [ -z {repair_command} ]; then
# pure Python wheel or empty repair command
mv "$built_wheel" /tmp/repaired_wheels
else
auditwheel repair "$built_wheel" -w /tmp/delocated_wheel
sh -c {repair_command} repair_command "$built_wheel"
fi
delocated_wheel=(/tmp/delocated_wheel/*.whl)
repaired_wheels=(/tmp/repaired_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 "${{repaired_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
mv "${{repaired_wheels[@]}}" /output
for repaired_wheel in "${{repaired_wheels[@]}}"; do chown {uid}:{gid} "/output/$(basename "$repaired_wheel")"; done
done
'''.format(
package_name=package_name,
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, python='python', pip='pip', project='/project') if test_command else ''
prepare_command(test_command, project='/project') if test_command else ''
),
before_build=shlex_quote(
prepare_command(before_build, python='python', pip='pip', project='/project') if before_build else ''
prepare_command(before_build, project='/project') if before_build else ''
),
build_verbosity_flag=' '.join(get_build_verbosity_extra_flags(build_verbosity)),
repair_command=shlex_quote(
prepare_command(repair_command, wheel='"$1"', dest_dir='/tmp/repaired_wheels') if repair_command else ''
),
environment_exports='\n'.join(environment.as_shell_commands()),
uid=os.getuid(),
gid=os.getgid(),
)
docker_process = subprocess.Popen([
'docker',
'run',
'--env',
'CIBUILDWHEEL',
'--rm',
'-i',
'-v', '%s:/project' % os.path.abspath(project_dir),
'-v', '%s:/output' % os.path.abspath(output_dir),
'-v', '/:/host',
docker_image,
'/bin/bash'],
stdin=subprocess.PIPE, universal_newlines=True)
def run_docker(command, stdin_str=None):
print('docker command: docker {}'.format(' '.join(map(shlex_quote, command))))
if stdin_str is None:
subprocess.check_call(['docker'] + command)
else:
args = ['docker'] + command
process = subprocess.Popen(args, stdin=subprocess.PIPE, universal_newlines=True)
try:
process.communicate(stdin_str)
except KeyboardInterrupt:
process.kill()
process.wait()
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, args)
container_name = 'cibuildwheel-{}'.format(uuid.uuid4())
try:
docker_process.communicate(bash_script)
except KeyboardInterrupt:
docker_process.kill()
docker_process.wait()
if docker_process.returncode != 0:
run_docker(['create',
'--env', 'CIBUILDWHEEL',
'--name', container_name,
'-i',
'-v', '/:/host', # ignored on Circle
docker_image, '/bin/bash'])
run_docker(['cp', os.path.abspath(project_dir) + '/.', container_name + ':/project'])
run_docker(['start', '-i', '-a', container_name], stdin_str=bash_script)
run_docker(['cp', container_name + ':/output/.', os.path.abspath(output_dir)])
except subprocess.CalledProcessError:
exit(1)
finally:
# Still gets executed, even when 'exit(1)' gets called
run_docker(['rm', '--force', '-v', container_name])
+94 -50
View File
@@ -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
@@ -7,17 +8,30 @@ try:
except ImportError:
from pipes import quote as shlex_quote
from .util import prepare_command
from .util import prepare_command, get_build_verbosity_extra_flags
def build(project_dir, package_name, output_dir, test_command, test_requires, before_build, skip, environment):
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.14/python-2.7.14-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.5/python-3.6.5-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.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, test_extras, before_build, build_verbosity, build_selector, repair_command, environment):
abs_project_dir = os.path.abspath(project_dir)
temp_dir = tempfile.mkdtemp(prefix='cibuildwheel')
built_wheel_dir = os.path.join(temp_dir, 'built_wheel')
repaired_wheel_dir = os.path.join(temp_dir, 'repaired_wheel')
python_configurations = get_python_configurations(build_selector)
get_pip_url = 'https://bootstrap.pypa.io/get-pip.py'
get_pip_script = '/tmp/get-pip.py'
@@ -35,16 +49,10 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
return subprocess.check_call(args, env=env, cwd=cwd, shell=shell)
abs_project_dir = os.path.abspath(project_dir)
# get latest pip once and for all
call(['curl', '-L', '-o', get_pip_script, get_pip_url])
for config in python_configurations:
if skip(config.identifier):
print('cibuildwheel: Skipping build %s' % config.identifier, file=sys.stderr)
continue
# if this version of python isn't installed, get it from python.org and install
python_package_identifier = 'org.python.Python.PythonFramework-%s' % config.version
if python_package_identifier not in installed_system_packages:
@@ -52,66 +60,102 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
call(['curl', '-L', '-o', '/tmp/Python.pkg', config.url])
# install
call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/'])
# patch open ssl
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)
assert os.path.exists(os.path.join(installation_bin_path, 'python3' if config.version[0] == '3' else 'python'))
# Python bin folders on Mac don't symlink python3 to python, so we do that
# so `python` and `pip` always point to the active configuration.
if os.path.exists('/tmp/cibw_bin'):
shutil.rmtree('/tmp/cibw_bin')
os.makedirs('/tmp/cibw_bin')
if config.version[0] == '3':
os.symlink(os.path.join(installation_bin_path, 'python3'), '/tmp/cibw_bin/python')
os.symlink(os.path.join(installation_bin_path, 'python3-config'), '/tmp/cibw_bin/python-config')
os.symlink(os.path.join(installation_bin_path, 'pip3'), '/tmp/cibw_bin/pip')
env = os.environ.copy()
env['PATH'] = os.pathsep.join([
'/Library/Frameworks/Python.framework/Versions/%s/bin' % config.version,
'/tmp/cibw_bin',
installation_bin_path,
env['PATH'],
])
env = environment.as_dictionary(prev_environment=env)
python = 'python3' if config.version[0] == '3' else 'python2'
pip = 'pip3' if config.version[0] == '3' else 'pip2'
# check what version we're on
call(['which', python], env=env)
call([python, '--version'], env=env)
call(['which', 'python'], env=env)
call(['python', '--version'], env=env)
# install pip & wheel
call([python, get_pip_script, '--no-setuptools', '--no-wheel'], env=env)
call([pip, '--version'], env=env)
call([pip, 'install', 'wheel'], env=env)
call([pip, 'install', 'delocate'], env=env)
# setup dirs
if os.path.exists('/tmp/built_wheel'):
shutil.rmtree('/tmp/built_wheel')
os.makedirs('/tmp/built_wheel')
if os.path.exists('/tmp/delocated_wheel'):
shutil.rmtree('/tmp/delocated_wheel')
os.makedirs('/tmp/delocated_wheel')
call(['python', get_pip_script, '--no-setuptools', '--no-wheel'], env=env, cwd="/tmp")
assert os.path.exists(os.path.join(installation_bin_path, 'pip'))
call(['pip', '--version'], env=env)
call(['pip', 'install', '--upgrade', 'setuptools', 'wheel', 'delocate'], env=env)
# run the before_build command
if before_build:
before_build_prepared = prepare_command(before_build, python=python, pip=pip, project=abs_project_dir)
before_build_prepared = prepare_command(before_build, project=abs_project_dir)
call(before_build_prepared, env=env, shell=True)
# build the wheel
call([pip, 'wheel', abs_project_dir, '-w', '/tmp/built_wheel', '--no-deps'], env=env)
built_wheel = glob('/tmp/built_wheel/*.whl')[0]
if os.path.exists(built_wheel_dir):
shutil.rmtree(built_wheel_dir)
os.makedirs(built_wheel_dir)
call(['pip', 'wheel', abs_project_dir, '-w', built_wheel_dir, '--no-deps'] + get_build_verbosity_extra_flags(build_verbosity), env=env)
built_wheel = glob(os.path.join(built_wheel_dir, '*.whl'))[0]
if built_wheel.endswith('none-any.whl'):
# pure python wheel - just move
shutil.move(built_wheel, '/tmp/delocated_wheel')
# repair the wheel
if os.path.exists(repaired_wheel_dir):
shutil.rmtree(repaired_wheel_dir)
os.makedirs(repaired_wheel_dir)
if built_wheel.endswith('none-any.whl') or not repair_command:
# pure Python wheel or empty repair command
shutil.move(built_wheel, repaired_wheel_dir)
else:
# list the dependencies
call(['delocate-listdeps', built_wheel], env=env)
# rebuild the wheel with shared libraries included and place in output dir
call(['delocate-wheel', '-w', '/tmp/delocated_wheel', built_wheel], env=env)
delocated_wheel = glob('/tmp/delocated_wheel/*.whl')[0]
repair_command_prepared = prepare_command(repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
call(repair_command_prepared, env=env, shell=True)
repaired_wheel = glob(os.path.join(repaired_wheel_dir, '*.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', repaired_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, python=python, pip=pip, project=abs_project_dir)
call(shlex.split(test_command_prepared), cwd=os.environ['HOME'], env=env)
test_command_prepared = prepare_command(test_command, project=abs_project_dir)
call(test_command_prepared, cwd=os.environ['HOME'], env=virtualenv_env, shell=True)
# we're all done here; move it to output
shutil.move(delocated_wheel, output_dir)
# 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(repaired_wheel))
shutil.move(repaired_wheel, dst)
@@ -0,0 +1,88 @@
:: To build extensions for 64 bit Python 3, we need to configure environment
:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1)
::
:: To build extensions for 64 bit Python 2, we need to configure environment
:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of:
:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0)
::
:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific
:: environment configurations.
::
:: Note: this script needs to be run with the /E:ON and /V:ON flags for the
:: cmd interpreter, at least for (SDK v7.0)
::
:: More details at:
:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
:: http://stackoverflow.com/a/13751649/163740
::
:: Author: Olivier Grisel
:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
::
:: Notes about batch files for Python people:
::
:: Quotes in values are literally part of the values:
:: SET FOO="bar"
:: FOO is now five characters long: " b a r "
:: If you don't want quotes, don't include them on the right-hand side.
::
:: The CALL lines at the end of this file look redundant, but if you move them
:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y
:: case, I don't know why.
@ECHO OFF
SET COMMAND_TO_RUN=%*
SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
SET WIN_WDK=c:\Program Files (x86)\Windows Kits\10\Include\wdf
:: Extract the major and minor versions, and allow for the minor version to be
:: more than 9. This requires the version number to have two dots in it.
SET MAJOR_PYTHON_VERSION=%PYTHON_VERSION:~0,1%
IF "%PYTHON_VERSION:~3,1%" == "." (
SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1%
) ELSE (
SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,2%
)
:: Based on the Python version, determine what SDK version to use, and whether
:: to set the SDK for 64-bit.
IF %MAJOR_PYTHON_VERSION% == 2 (
SET WINDOWS_SDK_VERSION="v7.0"
SET SET_SDK_64=Y
) ELSE (
IF %MAJOR_PYTHON_VERSION% == 3 (
SET WINDOWS_SDK_VERSION="v7.1"
IF %MINOR_PYTHON_VERSION% LEQ 4 (
SET SET_SDK_64=Y
) ELSE (
SET SET_SDK_64=N
IF EXIST "%WIN_WDK%" (
:: See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/
REN "%WIN_WDK%" 0wdf
)
)
) ELSE (
ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%"
EXIT 1
)
)
IF %PYTHON_ARCH% == 64 (
IF %SET_SDK_64% == Y (
ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture
SET DISTUTILS_USE_SDK=1
SET MSSdk=1
"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
ECHO Executing: %COMMAND_TO_RUN%
call %COMMAND_TO_RUN% || EXIT 1
) ELSE (
ECHO Using default MSVC build environment for 64 bit architecture
ECHO Executing: %COMMAND_TO_RUN%
call %COMMAND_TO_RUN% || EXIT 1
)
) ELSE (
ECHO Using default MSVC build environment for 32 bit architecture
ECHO Executing: %COMMAND_TO_RUN%
call %COMMAND_TO_RUN% || EXIT 1
)
+23 -12
View File
@@ -1,27 +1,38 @@
from fnmatch import fnmatch
import warnings
def prepare_command(command, python, pip, project):
def prepare_command(command, **kwargs):
'''
Preprocesses a command by expanding variables like {python} or {pip}.
Preprocesses a command by expanding variables like {python}.
For example, used for the before_build option, where the user would
like to run a command like `python setup.py test`. If the command should run on
Python 3, the user could write `{python} setup.py test`. This command would expand
it out to python2 or python3 as appropriate.
For example, used in the test_command option to specify the path to the
project's root.
'''
return command.format(python=python, pip=pip, project=project)
return command.format(python='python', pip='pip', **kwargs)
class BuildSkipper(object):
def __init__(self, skip_config):
self.patterns = skip_config.split()
def get_build_verbosity_extra_flags(level):
if level > 0:
return ['-' + level * 'v']
elif level < 0:
return ['-' + -level * 'q']
else:
return []
class BuildSelector(object):
def __init__(self, build_config, skip_config):
self.build_patterns = build_config.split()
self.skip_patterns = skip_config.split()
def __call__(self, build_id):
return any(fnmatch(build_id, pattern) for pattern in self.patterns)
def match_any(patterns):
return any(fnmatch(build_id, pattern) for pattern in patterns)
return match_any(self.build_patterns) and not match_any(self.skip_patterns)
def __repr__(self):
return 'BuildSkipper(%r)' % ' '.join(self.patterns)
return 'BuildSelector({!r} - {!r})'.format(' '.join(self.build_patterns), ' '.join(self.skip_patterns))
# Taken from https://stackoverflow.com/a/107717
+153 -60
View File
@@ -1,102 +1,195 @@
from __future__ import print_function
import os, tempfile, subprocess, sys, shutil
try:
from urllib2 import urlopen
except ImportError:
from urllib.request import urlopen
import os, tempfile, subprocess, shutil, sys
from collections import namedtuple
from glob import glob
from .util import prepare_command, Unbuffered
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
def build(project_dir, package_name, output_dir, test_command, test_requires, before_build, skip, environment):
# Python under AppVeyor/Windows seems to be buffering by default, giving problems interleaving subprocess call output with unflushed calls to 'print'
sys.stdout.flush()
sys.stdout = Unbuffered(sys.stdout)
IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
IS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows'
# run_with_env is a cmd file that sets the right environment variables to
run_with_env = os.path.join(tempfile.gettempdir(), 'appveyor_run_with_env.cmd')
if not os.path.exists(run_with_env):
with open(run_with_env, 'wb') as f:
request = urlopen('https://github.com/ogrisel/python-appveyor-demo/raw/09a1c8672e5015a74d8f69d07add6ee803c176ec/appveyor/run_with_env.cmd')
f.write(request.read())
def shell(args, env=None, cwd=None):
# print the command executing for the logs
print('+ ' + ' '.join(args))
args = ['cmd', '/E:ON', '/V:ON', '/C', run_with_env] + args
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
def get_python_path(config):
nuget_args = get_nuget_args(config)
return os.path.join(nuget_args[-1], nuget_args[0] + "." + config.version, "tools")
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier', 'path'])
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'])
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.3.x', arch="32", identifier='cp33-win32', path='C:\Python33'),
PythonConfiguration(version='3.3.x', arch="64", identifier='cp33-win_amd64', path='C:\Python33-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='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_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
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, test_extras, before_build, build_verbosity, build_selector, repair_command, 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.
def shell(args, env=None, cwd=None):
# print the command executing for the logs
print('+ ' + ' '.join(args))
args = ['cmd', '/E:ON', '/V:ON', '/C', run_with_env] + args
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
abs_project_dir = os.path.abspath(project_dir)
temp_dir = tempfile.mkdtemp(prefix='cibuildwheel')
built_wheel_dir = os.path.join(temp_dir, 'built_wheel')
repaired_wheel_dir = os.path.join(temp_dir, 'repaired_wheel')
# 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:
if skip(config.identifier):
print('cibuildwheel: Skipping build %s' % config.identifier, file=sys.stderr)
continue
# setup dirs
if os.path.exists(built_wheel_dir):
shutil.rmtree(built_wheel_dir)
os.makedirs(built_wheel_dir)
# install Python
config_python_path = get_python_path(config)
simple_shell([nuget, "install"] + get_nuget_args(config))
assert os.path.exists(os.path.join(config_python_path, 'python.exe'))
# set up PATH and environment variables for run_with_env
env = os.environ.copy()
# set up environment variables for run_with_env
env['PYTHON_VERSION'] = config.version
env['PYTHON_ARCH'] = config.arch
env['PATH'] = os.pathsep.join([
config.path,
os.path.join(config.path, 'Scripts'),
config_python_path,
os.path.join(config_python_path, 'Scripts'),
env['PATH']
])
# update env with results from CIBW_ENVIRONMENT
env = environment.as_dictionary(prev_environment=env)
# for the logs - check we're running the right version of python
shell(['python', '--version'], env=env)
shell(['python', '-c', '"import struct; print(struct.calcsize(\'P\') * 8)\"'], env=env)
simple_shell(['where', 'python'], env=env)
simple_shell(['python', '--version'], env=env)
simple_shell(['python', '-c', '"import struct; print(struct.calcsize(\'P\') * 8)\"'], env=env)
# make sure pip is installed
if not os.path.exists(os.path.join(config_python_path, 'Scripts', 'pip.exe')):
simple_shell(['python', get_pip_script], env=env, cwd="C:\\cibw")
assert os.path.exists(os.path.join(config_python_path, 'Scripts', 'pip.exe'))
# prepare the Python environment
shell(['python', '-m', 'pip', 'install', '--upgrade', 'pip'],
env=env)
shell(['pip', 'install', 'wheel'], env=env)
simple_shell(['python', '-m', 'pip', 'install', '--upgrade', 'pip'], env=env)
simple_shell(['pip', '--version'], env=env)
simple_shell(['pip', 'install', '--upgrade', 'setuptools', 'wheel'], env=env)
# run the before_build command
if before_build:
before_build_prepared = prepare_command(before_build, python='python', pip='pip', project=abs_project_dir)
before_build_prepared = prepare_command(before_build, project=abs_project_dir)
shell([before_build_prepared], env=env)
# build the wheel
shell(['pip', 'wheel', abs_project_dir, '-w', built_wheel_dir, '--no-deps'], env=env)
built_wheel = glob(built_wheel_dir+'/*.whl')[0]
if os.path.exists(built_wheel_dir):
shutil.rmtree(built_wheel_dir)
os.makedirs(built_wheel_dir)
shell(['pip', 'wheel', abs_project_dir, '-w', built_wheel_dir, '--no-deps'] + get_build_verbosity_extra_flags(build_verbosity), env=env)
built_wheel = glob(os.path.join(built_wheel_dir, '*.whl'))[0]
# install the wheel
shell(['pip', 'install', built_wheel], env=env)
# repair the wheel
if os.path.exists(repaired_wheel_dir):
shutil.rmtree(repaired_wheel_dir)
os.makedirs(repaired_wheel_dir)
if built_wheel.endswith('none-any.whl') or not repair_command:
# pure Python wheel or empty repair command
shutil.move(built_wheel, repaired_wheel_dir)
else:
repair_command_prepared = prepare_command(repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
shell([repair_command_prepared], env=env)
repaired_wheel = glob(os.path.join(repaired_wheel_dir, '*.whl'))[0]
# 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', repaired_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, python='python', pip='pip', project=abs_project_dir)
shell([test_command_prepared], cwd='c:\\', env=env)
test_command_prepared = prepare_command(test_command, project=abs_project_dir)
shell([test_command_prepared], cwd='c:\\', env=virtualenv_env)
# we're all done here; move it to output
shutil.move(built_wheel, output_dir)
# 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(repaired_wheel))
if os.path.isfile(dst):
os.remove(dst)
shutil.move(repaired_wheel, dst)
+30
View File
@@ -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.
+36
View File
@@ -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.
+88
View File
@@ -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);
+5
View File
@@ -0,0 +1,5 @@
$('.rst-content pre')
.prev('blockquote')
.addClass('code-block-filename');
+39
View File
@@ -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',
)
```
+11
View File
@@ -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
)
+501
View File
@@ -0,0 +1,501 @@
## 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.
To specify more than one environment variable separate it by space.
Platform-specific variants also available:<br/>
`CIBW_ENVIRONMENT_MACOS` | `CIBW_ENVIRONMENT_WINDOWS` | `CIBW_ENVIRONMENT_LINUX`
#### 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"
# Set two flags
CIBW_ENVIRONMENT: "BUILD_TIME=$(date) SAMPLE_TEXT=\"sample text\""
```
!!! 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 and will be replaced by `cibuildwheel`.
On Linux and macOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`.
Platform-specific variants also available:<br/>
`CIBW_BEFORE_BUILD_MACOS` | `CIBW_BEFORE_BUILD_WINDOWS` | `CIBW_BEFORE_BUILD_LINUX`
#### 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 .
```
### `CIBW_REPAIR_WHEEL_COMMAND` {: #repair-wheel-command}
> Execute a shell command to repair each (non-pure Python) built wheel
Default:
- on Linux: `'auditwheel repair -w {dest_dir} {wheel}'`
- on macOS: `'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}'`
- on Windows: `''`
A shell command to repair a built wheel by copying external library dependencies into the wheel tree and relinking them.
The command is run on each built wheel (except for pure Python ones) before testing it.
The following placeholders must be used inside the command and will be replaced by `cibuildwheel`:
- `{wheel}` for the absolute path to the built wheel
- `{dest_dir}` for the absolute path of the directory where to create the repaired wheel.
On Linux and macOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`.
Platform-specific variants also available:<br/>
`CIBW_REPAIR_WHEEL_COMMAND_MACOS` | `CIBW_REPAIR_WHEEL_COMMAND_WINDOWS` | `CIBW_REPAIR_WHEEL_COMMAND_LINUX`
#### Examples
```yaml
# don't repair macOS wheels
CIBW_REPAIR_WHEEL_COMMAND_MACOS: ""
# pass the `--lib-sdir .` flag to auditwheel on Linux
CIBW_REPAIR_WHEEL_COMMAND_LINUX: "auditwheel repair --lib-sdir . -w {dest_dir} {wheel}"
```
### `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`, `manylinux2010` or `manylinux2014` 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-, manylinux2010- or manylinux2014-compatible in order to produce valid `manylinux1`/`manylinux2010`/`manylinux2014` wheels (see https://github.com/pypa/manylinux, [PEP 513](https://www.python.org/dev/peps/pep-0513/), [PEP 571](https://www.python.org/dev/peps/pep-0571/ and [PEP 599](https://www.python.org/dev/peps/pep-0599/) 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)"`).
Note that `manylinux2014` doesn't support builds with Python 2.7 - when building with `manylinux2014`, skip Python 2.7 using `CIBW_SKIP` (see example below).
#### 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 the manylinux2014 image
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
CIBW_MANYLINUX_I686_IMAGE: manylinux2014
CIBW_SKIP: cp27-manylinux*
# 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 each built wheel
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 macOS, the command is run in a shell, so you can write things like `cmd1 && cmd2`.
Platform-specific variants also available:<br/>
`CIBW_TEST_COMMAND_MACOS` | `CIBW_TEST_COMMAND_WINDOWS` | `CIBW_TEST_COMMAND_LINUX`
#### 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
```
### `CIBW_TEST_REQUIRES` {: #test-requires}
> Install Python dependencies before running the tests
Space-separated list of dependencies required for running the tests.
Platform-specific variants also available:<br/>
`CIBW_TEST_REQUIRES_MACOS` | `CIBW_TEST_REQUIRES_WINDOWS` | `CIBW_TEST_REQUIRES_LINUX`
#### 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
```
### `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`.
Platform-specific variants also available:<br/>
`CIBW_TEST_EXTRAS_MACOS` | `CIBW_TEST_EXTRAS_WINDOWS` | `CIBW_TEST_EXTRAS_LINUX`
#### Examples
```yaml
# will cause the wheel to be installed with `pip install <wheel_file>[test,qt]`
CIBW_TEST_EXTRAS: test,qt
```
## 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.
Platform-specific variants also available:<br/>
`CIBW_BUILD_VERBOSITY_MACOS` | `CIBW_BUILD_VERBOSITY_WINDOWS` | `CIBW_BUILD_VERBOSITY_LINUX`
#### Examples
```yaml
# increase pip debugging output
CIBW_BUILD_VERBOSITY: 1
```
## 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>
+203
View File
@@ -0,0 +1,203 @@
---
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.1.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.1.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.1.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/windows] {: #travis-ci}
To build Linux, Mac, and Windows wheels on Travis CI, create a `.travis.yml` file in your repo.
> .travis.yml
```yaml
language: python
jobs:
include:
# perform a linux build
- services: docker
# and a mac build
- os: osx
language: shell
# and a windows build
- os: windows
language: shell
before_install:
- choco install python --version 3.8.0
- export PATH="/c/Python38:/c/Python38/Scripts:$PATH"
env:
global:
- TWINE_USERNAME=joerick
# Note: TWINE_PASSWORD is set in Travis settings
install:
- python -m pip install twine cibuildwheel==1.1.0
script:
# build the wheels, put them into './wheelhouse'
- python -m cibuildwheel --output-dir wheelhouse
```
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.1.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.1.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 [linux/windows] {: #appveyor}
To build Linux and Windows wheels on AppVeyor, create an `appveyor.yml` file in your repo.
> appveyor.yml
```yaml
image:
- Ubuntu
- Visual Studio 2015
build_script:
# windows
- cmd: pip install cibuildwheel==1.1.0
- cmd: cibuildwheel --output-dir wheelhouse
# linux
- sh: "${HOME}/.localpython3.7.4/bin/python3 -m pip install cibuildwheel==1.1.0"
- sh: "${HOME}/.localpython3.7.4/bin/python3 -m 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>
+34
View File
@@ -0,0 +1,34 @@
# As written, this configuration will build your wheels on every
# commit, but will only push to PyPI on tagged commits.
language: python
jobs:
include:
# perform a linux build
- services: docker
# and a mac build
- os: osx
language: shell
# and a windows build
- os: windows
language: shell
before_install:
- choco install python --version 3.8.0
- export PATH="/c/Python38:/c/Python38/Scripts:$PATH"
env:
global:
- TWINE_USERNAME=joerick
# Note: TWINE_PASSWORD is set in Travis settings
install:
- python -m pip install twine cibuildwheel==1.0.0
script:
# build the wheels, put them into './wheelhouse'
- python -m cibuildwheel --output-dir wheelhouse
after_success:
# if the release was tagged, upload them to PyPI
- if [[ $TRAVIS_TAG ]]; then python -m twine upload wheelhouse/*.whl; fi
+77
View File
@@ -0,0 +1,77 @@
# In this configuration, the package is tested against multiple versions of python
# on Linux and on one version of Python on Windows. If and only if all tests pass
# will the wheels be built and deployed. Further, deployment is only initiated if
# the current branch is "master", the current commit is tagged, and the current
# repo is yours (e.g. it won't run on a Pull Request). For convenience, a source
# distribution is also created.
language: python
python:
- 3.5
- 3.6
- 3.7
- 3.8
before_install:
- |
if [[ "$TRAVIS_OS_NAME" = windows ]]; then
choco install python --version 3.8.0
export PATH="/c/Python38:/c/Python38/Scripts:$PATH"
fi
install:
- python -m pip install pytest
script:
- python setup.py install
- pytest
stages:
- test
# Only execute deployment stage on master branch, tagged commits,
# and from your repository (e.g. not PRs). Replace with your repo name.
- name: deploy
if: branch = master AND tag IS PRESENT AND repo = joerick/cibuildwheel
jobs:
include:
# Optional: run a test on Windows
- os: windows
language: shell
name: Test on Windows
# Deploy source distribution
- stage: deploy
name: Deploy source distribution
install: skip
script: python setup.py sdist --formats=gztar
after_success: python -m twine upload --skip-existing dist/*.tar.gz
# Deploy on linux
- stage: deploy
name: Build and deploy Linux wheels
services: docker
install: python -m pip install twine cibuildwheel==1.0.0
script: python -m cibuildwheel --output-dir wheelhouse
after_success: python -m twine upload --skip-existing wheelhouse/*.whl
# Deploy on mac
- stage: deploy
name: Build and deploy macOS wheels
os: osx
language: shell
install: python -m pip install twine cibuildwheel==1.0.0
script: python -m cibuildwheel --output-dir wheelhouse
after_success: python -m twine upload --skip-existing wheelhouse/*.whl
# Deploy on windows
- stage: deploy
name: Build and deploy Windows wheels
os: windows
language: shell
install: python -m pip install twine cibuildwheel==1.0.0
script: python -m cibuildwheel --output-dir wheelhouse
after_success: python -m twine upload --skip-existing wheelhouse/*.whl
env:
global:
- TWINE_USERNAME=joerick
# Note: TWINE_PASSWORD is set in Travis settings
+32
View File
@@ -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
+2
View File
@@ -1,2 +1,4 @@
-e .
-e ./docs/mkdocs_include_markdown_plugin
pytest
mkdocs==1.0.4
+8 -1
View File
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.7.2
current_version = 1.1.0
commit = True
tag = True
message = Bump version
@@ -12,3 +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
+15 -4
View File
@@ -1,30 +1,41 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, io
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
this_directory = os.path.dirname(__file__)
with io.open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
long_description = f.read()
setup(
name='cibuildwheel',
version='0.7.2',
install_requires=['bashlex'],
version='1.1.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',
long_description=long_description,
long_description_content_type='text/markdown',
author="Joe Rickerby",
author_email='joerick@mac.com',
url='https://github.com/joerick/cibuildwheel',
packages=['cibuildwheel',],
license="BSD",
zip_safe=False,
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',
'Natural Language :: English',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Development Status :: 4 - Beta',
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Software Development :: Build Tools',
+25
View File
@@ -0,0 +1,25 @@
import os
import utils
project_dir = os.path.dirname(__file__)
def test():
# build the wheels
actual_wheels = utils.cibuildwheel_run(project_dir)
# check that the expected wheels are produced
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
def test_build_identifiers():
# check that the number of expected wheels matches the number of build
# identifiers
# 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)
+51
View File
@@ -0,0 +1,51 @@
import os, subprocess
import pytest
import utils
def test():
project_dir = os.path.dirname(__file__)
# build and test the wheels
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_TEST_REQUIRES': 'nose',
# 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')
assert set(actual_wheels) == set(expected_wheels)
def test_extras_require():
project_dir = os.path.dirname(__file__)
# build and test the wheels
actual_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')
assert set(actual_wheels) == set(expected_wheels)
def test_failing_test(tmp_path):
'''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, output_dir=tmp_path, 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(str(tmp_path))) == 0
-4
View File
@@ -1,4 +0,0 @@
{
"CIBW_TEST_REQUIRES": "nose",
"CIBW_TEST_COMMAND": "nosetests {project}/test"
}
+1
View File
@@ -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",
)
+17
View File
@@ -0,0 +1,17 @@
import os
import utils
def test():
project_dir = os.path.dirname(__file__)
# build the wheels
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
# write python version information to a temporary file, this is
# checked in setup.py
'CIBW_BEFORE_BUILD': '''python -c "import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('/tmp/pythonexecutable.txt', 'w').write(sys.executable)"''',
'CIBW_BEFORE_BUILD_WINDOWS': '''python -c "import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('c:\\pythonexecutable.txt', 'w').write(sys.executable)"''',
})
# also check that we got the right wheels
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
-4
View File
@@ -1,4 +0,0 @@
{
"CIBW_BEFORE_BUILD": "{python} -c \"import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)\" && {python} -c \"import sys; open('/tmp/pythonexecutable.txt', 'w').write(sys.executable)\"",
"CIBW_BEFORE_BUILD_WINDOWS": "{python} -c \"import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)\" && {python} -c \"import sys; open('c:\\pythonexecutable.txt', 'w').write(sys.executable)\""
}
+16 -17
View File
@@ -1,24 +1,23 @@
from setuptools import setup, Extension
import sys, os
if sys.argv[-1] != '--name':
# assert that the Python version as written to pythonversion.txt in the CIBW_BEFORE_BUILD step
# is the same one as is currently running.
version_file = 'c:\\pythonversion.txt' if sys.platform == 'win32' else '/tmp/pythonversion.txt'
with open(version_file) as f:
stored_version = f.read()
print('stored_version', stored_version)
print('sys.version', sys.version)
assert stored_version == sys.version
# assert that the Python version as written to pythonversion.txt in the CIBW_BEFORE_BUILD step
# is the same one as is currently running.
version_file = 'c:\\pythonversion.txt' if sys.platform == 'win32' else '/tmp/pythonversion.txt'
with open(version_file) as f:
stored_version = f.read()
print('stored_version', stored_version)
print('sys.version', sys.version)
assert stored_version == sys.version
# check that the executable also was written
executable_file = 'c:\\pythonexecutable.txt' if sys.platform == 'win32' else '/tmp/pythonexecutable.txt'
with open(executable_file) as f:
stored_executable = f.read()
print('stored_executable', stored_executable)
print('sys.executable', sys.executable)
# windows/mac are case insensitive
assert os.path.realpath(stored_executable).lower() == os.path.realpath(sys.executable).lower()
# check that the executable also was written
executable_file = 'c:\\pythonexecutable.txt' if sys.platform == 'win32' else '/tmp/pythonexecutable.txt'
with open(executable_file) as f:
stored_executable = f.read()
print('stored_executable', stored_executable)
print('sys.executable', sys.executable)
# windows/mac are case insensitive
assert os.path.realpath(stored_executable).lower() == os.path.realpath(sys.executable).lower()
setup(
name="spam",
-2
View File
@@ -1,2 +0,0 @@
3.6.0 (default, Feb 7 2017, 23:55:32)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]
+16
View File
@@ -0,0 +1,16 @@
import os
import utils
def test():
project_dir = os.path.dirname(__file__)
# build the wheels
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BUILD': 'cp3?-*',
'CIBW_SKIP': 'cp37-*',
})
# 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 ('-cp37' not in w)]
assert set(actual_wheels) == set(expected_wheels)
+14
View File
@@ -0,0 +1,14 @@
from setuptools import setup, Extension
import sys
# explode if run on Python 2.7 or Python 3.4 (these should be skipped)
if sys.version_info[0:2] == (2, 7):
raise Exception('Python 2.7 should not be built')
if sys.version_info[0:2] == (3, 4):
raise Exception('Python 3.4 should be skipped')
setup(
name="spam",
ext_modules=[Extension('spam', sources=['spam.c'])],
version="0.1.0",
)
-3
View File
@@ -1,3 +0,0 @@
{
"CIBW_SKIP": "cp26-* cp33-*"
}
-15
View File
@@ -1,15 +0,0 @@
from setuptools import setup, Extension
import sys
if sys.argv[-1] != '--name':
# explode if run on Python 2.6 or Python 3.3 (these should be skipped)
if sys.version_info[0:2] == (2, 6):
raise Exception('Python 2.6 should be skipped')
if sys.version_info[0:2] == (3, 3):
raise Exception('Python 3.3 should be skipped')
setup(
name="spam",
ext_modules=[Extension('spam', sources=['spam.c'])],
version="0.1.0",
)
-2
View File
@@ -1,2 +0,0 @@
3.6.0 (default, Feb 7 2017, 23:55:32)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]
+17
View File
@@ -0,0 +1,17 @@
import os
import utils
def test():
project_dir = os.path.dirname(__file__)
# write some information into the CIBW_ENVIRONMENT, for expansion and
# insertion into the environment by cibuildwheel. This is checked
# in setup.py
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_ENVIRONMENT': '''CIBW_TEST_VAR="a b c" CIBW_TEST_VAR_2=1 CIBW_TEST_VAR_3="$(echo 'test string 3')" PATH=$PATH:/opt/cibw_test_path''',
'CIBW_ENVIRONMENT_WINDOWS': '''CIBW_TEST_VAR="a b c" CIBW_TEST_VAR_2=1 CIBW_TEST_VAR_3="$(echo 'test string 3')" PATH="$PATH;/opt/cibw_test_path"''',
})
# also check that we got the right wheels built
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
-4
View File
@@ -1,4 +0,0 @@
{
"CIBW_ENVIRONMENT": "CIBW_TEST_VAR=\"a b c\" CIBW_TEST_VAR_2=1 CIBW_TEST_VAR_3=\"$(echo 'test string 3')\" PATH=$PATH:/opt/cibw_test_path",
"CIBW_ENVIRONMENT_WINDOWS": "CIBW_TEST_VAR=\"a b c\" CIBW_TEST_VAR_2=1 CIBW_TEST_VAR_3=\"$(echo 'test string 3')\" PATH=\"$PATH;/opt/cibw_test_path\""
}
+12 -13
View File
@@ -1,20 +1,19 @@
from setuptools import setup, Extension
import sys, os
if sys.argv[-1] != '--name':
# explode if environment isn't correct, as set in CIBW_ENVIRONMENT
CIBW_TEST_VAR = os.environ.get('CIBW_TEST_VAR')
CIBW_TEST_VAR_2 = os.environ.get('CIBW_TEST_VAR_2')
PATH = os.environ.get('PATH')
# explode if environment isn't correct, as set in CIBW_ENVIRONMENT
CIBW_TEST_VAR = os.environ.get('CIBW_TEST_VAR')
CIBW_TEST_VAR_2 = os.environ.get('CIBW_TEST_VAR_2')
PATH = os.environ.get('PATH')
if CIBW_TEST_VAR != 'a b c':
raise Exception('CIBW_TEST_VAR should equal "a b c". It was "%s"' % CIBW_TEST_VAR)
if CIBW_TEST_VAR_2 != '1':
raise Exception('CIBW_TEST_VAR_2 should equal "1". It was "%s"' % CIBW_TEST_VAR_2)
if '/opt/cibw_test_path' not in PATH:
raise Exception('PATH should contain "/opt/cibw_test_path". It was "%s"' % PATH)
if '$PATH' in PATH:
raise Exception('$PATH should be expanded in PATH. It was "%s"' % PATH)
if CIBW_TEST_VAR != 'a b c':
raise Exception('CIBW_TEST_VAR should equal "a b c". It was "%s"' % CIBW_TEST_VAR)
if CIBW_TEST_VAR_2 != '1':
raise Exception('CIBW_TEST_VAR_2 should equal "1". It was "%s"' % CIBW_TEST_VAR_2)
if '/opt/cibw_test_path' not in PATH:
raise Exception('PATH should contain "/opt/cibw_test_path". It was "%s"' % PATH)
if '$PATH' in PATH:
raise Exception('$PATH should be expanded in PATH. It was "%s"' % PATH)
setup(
-2
View File
@@ -1,2 +0,0 @@
3.6.0 (default, Feb 7 2017, 23:55:32)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]
@@ -0,0 +1,20 @@
import os, pytest
import utils
def test():
project_dir = os.path.dirname(__file__)
if utils.platform != 'linux':
pytest.skip('the test is only relevant to the linux build')
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'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 = [w for w in utils.expected_wheels('spam', '0.1.0')
if '-manylinux2010_i686' not in w]
assert set(actual_wheels) == set(expected_wheels)
-4
View File
@@ -1,4 +0,0 @@
{
"CIBW_MANYLINUX1_X86_64_IMAGE": "dockcross/manylinux-x64",
"CIBW_MANYLINUX1_I686_IMAGE": "dockcross/manylinux-x86"
}
+4 -5
View File
@@ -2,11 +2,10 @@ import os, sys
from setuptools import setup, Extension
if sys.argv[-1] != '--name':
# check that we're running in the correct docker image as specified in the
# environment options CIBW_MANYLINUX1_*_IMAGE
if 'linux' in sys.platform and not os.path.exists('/dockcross'):
raise Exception('/dockcross directory not found. Is this test running in the correct docker image?')
# check that we're running in the correct docker image as specified in the
# environment options CIBW_MANYLINUX1_*_IMAGE
if 'linux' in sys.platform and not os.path.exists('/dockcross'):
raise Exception('/dockcross directory not found. Is this test running in the correct docker image?')
setup(
name="spam",
+9
View File
@@ -0,0 +1,9 @@
import os
import utils
def test():
project_dir = os.path.dirname(__file__)
# this test checks that SSL is working in the build environment using
# some checks in setup.py.
utils.cibuildwheel_run(project_dir)
+20
View File
@@ -0,0 +1,20 @@
import ssl
import sys
from setuptools import setup, Extension
if sys.version_info[0] == 2:
from urllib2 import urlopen
else:
from urllib.request import urlopen
if sys.version_info[0:2] == (3, 3):
data = urlopen('https://www.nist.gov')
else:
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
data = urlopen('https://www.nist.gov', context=context)
setup(
name="spam",
ext_modules=[Extension('spam', sources=['spam.c'])],
version="0.1.0",
)
+48
View File
@@ -0,0 +1,48 @@
#include <Python.h>
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
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)
}
@@ -0,0 +1,27 @@
import os, pytest
import utils
@pytest.mark.parametrize('manylinux_image', ['manylinux1', 'manylinux2010', 'manylinux2014'])
def test(manylinux_image):
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 variable is necessary to fail on 'malloc_info' (on manylinux1) during compilation/linking,
# rather than when dynamically loading the Python
add_env = {
'CIBW_ENVIRONMENT': 'CFLAGS="$CFLAGS -Werror=implicit-function-declaration"',
'CIBW_MANYLINUX_X86_64_IMAGE': manylinux_image,
'CIBW_MANYLINUX_I686_IMAGE': manylinux_image,
}
if manylinux_image == 'manylinux2014':
add_env['CIBW_SKIP'] = 'cp27*' # not available on manylinux2014
actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env)
expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0', manylinux_versions=[manylinux_image])]
if manylinux_image == 'manylinux2014':
expected_wheels = [w for w in expected_wheels if '-cp27' not in w]
assert set(actual_wheels) == set(expected_wheels)
+7
View File
@@ -0,0 +1,7 @@
from setuptools import setup, Extension
setup(
name="spam",
ext_modules=[Extension('spam', sources=['spam.c'])],
version="0.1.0",
)
+68
View File
@@ -0,0 +1,68 @@
#include <Python.h>
#include <malloc.h>
#if !defined(__GLIBC_PREREQ)
#error "Must run on a glibc linux environment"
#endif
#if !__GLIBC_PREREQ(2, 5) /* manylinux1 is glibc 2.5 */
#error "Must run on a glibc >= 2.5 linux environment"
#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(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 17) /* manylinux2014 is glibc 2.17 */
// secure_getenv is only available in manylinux2014, ensuring
// that only a manylinux2014 wheel is produced
sts = (int)secure_getenv("NON_EXISTING_ENV_VARIABLE");
#elif defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10) /* manylinux2010 is glibc 2.12 */
// malloc_info is only available on manylinux2010+
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)
}
+13
View File
@@ -0,0 +1,13 @@
import os
import utils
project_dir = os.path.dirname(__file__)
def test():
# build the wheels
actual_wheels = utils.cibuildwheel_run(project_dir)
# check that the expected wheels are produced
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
+6
View File
@@ -0,0 +1,6 @@
[metadata]
name = spam
version = attr: spam.__version__
[options]
packages = find:
+8
View File
@@ -0,0 +1,8 @@
import os
from setuptools import setup, Extension
setup(
ext_modules=[Extension('spam.spam', sources=['spam/spam.c'])],
)
+1
View File
@@ -0,0 +1 @@
__version__ = "0.1.0"
+48
View File
@@ -0,0 +1,48 @@
#include <Python.h>
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
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)
}
+4
View File
@@ -0,0 +1,4 @@
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), 'shared'))
+126
View File
@@ -0,0 +1,126 @@
'''
Utility functions used by the cibuildwheel tests.
This file is added to the PYTHONPATH in the test runner at bin/run_test.py.
'''
import subprocess, sys, os, shutil
from tempfile import mkdtemp
from contextlib import contextmanager
IS_WINDOWS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
IS_WINDOWS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows'
# Python 2 does not have a tempfile.TemporaryDirectory context manager
@contextmanager
def TemporaryDirectoryIfNone(path):
_path = path or mkdtemp()
try:
yield _path
finally:
if path is None:
shutil.rmtree(_path)
def cibuildwheel_get_build_identifiers(project_path, env=None):
'''
Returns the list of build identifiers that cibuildwheel will try to build
for the current platform.
'''
cmd_output = subprocess.check_output(
[sys.executable, '-m', 'cibuildwheel', '--print-build-identifiers', project_path],
universal_newlines=True,
env=env,
)
return cmd_output.strip().split('\n')
def cibuildwheel_run(project_path, env=None, add_env=None, output_dir=None):
'''
Runs cibuildwheel as a subprocess, building the project at project_path.
Uses the current Python interpreter.
:param project_path: path of the project to be built.
:param env: full environment to be used, os.environ if None
:param add_env: environment used to update env
:param output_dir: directory where wheels are saved. If None, a temporary
directory will be used for the duration of the command.
:return: list of built wheels (file names).
'''
if env is None:
env = os.environ.copy()
if add_env is not None:
env.update(add_env)
with TemporaryDirectoryIfNone(output_dir) as _output_dir:
subprocess.check_call(
[sys.executable, '-m', 'cibuildwheel', '--output-dir', str(_output_dir), project_path],
env=env,
)
wheels = os.listdir(_output_dir)
return wheels
def expected_wheels(package_name, package_version, manylinux_versions=['manylinux1', 'manylinux2010']):
'''
Returns a list of expected wheels from a run of cibuildwheel.
'''
# per PEP 425 (https://www.python.org/dev/peps/pep-0425/), wheel files shall have name of the form
# {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl
# {python tag} and {abi tag} are closely related to the python interpreter used to build the wheel
# so we'll merge them below as python_abi_tag
python_abi_tags = ['cp27-cp27m', 'cp35-cp35m', 'cp36-cp36m', 'cp37-cp37m', 'cp38-cp38']
if platform == 'linux':
python_abi_tags.append('cp27-cp27mu') # python 2.7 has 2 different ABI on manylinux
platform_tags = []
for architecture in ['x86_64', 'i686']:
for manylinux_version in manylinux_versions:
platform_tags.append('{manylinux_version}_{architecture}'.format(
manylinux_version=manylinux_version, architecture=architecture
))
def get_platform_tags(python_abi_tag):
return platform_tags
elif platform == 'windows':
def get_platform_tags(python_abi_tag):
return ['win32', 'win_amd64']
elif platform == 'macos':
def get_platform_tags(python_abi_tag):
if python_abi_tag == 'cp38-cp38':
return ['macosx_10_9_x86_64']
else:
return ['macosx_10_6_intel']
else:
raise Exception('unsupported platform')
templates = []
for python_abi_tag in python_abi_tags:
for platform_tag in get_platform_tags(python_abi_tag):
templates.append('{package_name}-{package_version}-{python_abi_tag}-{platform_tag}.whl'.format(
package_name=package_name, package_version=package_version,
python_abi_tag=python_abi_tag, platform_tag=platform_tag
))
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 templates
platform = None
if 'CIBW_PLATFORM' in os.environ:
platform = os.environ['CIBW_PLATFORM']
elif sys.platform.startswith('linux'):
platform = 'linux'
elif sys.platform.startswith('darwin'):
platform = 'macos'
elif sys.platform in ['win32', 'cygwin']:
platform = 'windows'
else:
raise Exception('Unsupported platform')
+61
View File
@@ -0,0 +1,61 @@
from cibuildwheel.util import BuildSelector
def test_build():
build_selector = BuildSelector(build_config="cp3?-* *-manylinux1*", skip_config="")
assert build_selector('cp27-manylinux1_x86_64')
assert build_selector('cp36-manylinux1_x86_64')
assert build_selector('cp37-manylinux1_x86_64')
assert build_selector('cp27-manylinux1_i686')
assert build_selector('cp36-manylinux1_i686')
assert build_selector('cp37-manylinux1_i686')
assert not build_selector('cp27-macosx_10_6_intel')
assert build_selector('cp36-macosx_10_6_intel')
assert build_selector('cp37-macosx_10_6_intel')
assert not build_selector('cp27-win32')
assert build_selector('cp36-win32')
assert build_selector('cp37-win32')
assert not build_selector('cp27-win_amd64')
assert build_selector('cp36-win_amd64')
assert build_selector('cp37-win_amd64')
def test_skip():
build_selector = BuildSelector(build_config="*", skip_config="cp27-* cp3?-manylinux1_i686 cp36-win* *-win32")
assert not build_selector('cp27-manylinux1_x86_64')
assert build_selector('cp36-manylinux1_x86_64')
assert build_selector('cp37-manylinux1_x86_64')
assert not build_selector('cp27-manylinux1_i686')
assert not build_selector('cp36-manylinux1_i686')
assert not build_selector('cp37-manylinux1_i686')
assert not build_selector('cp27-macosx_10_6_intel')
assert build_selector('cp36-macosx_10_6_intel')
assert build_selector('cp37-macosx_10_6_intel')
assert not build_selector('cp27-win32')
assert not build_selector('cp36-win32')
assert not build_selector('cp37-win32')
assert not build_selector('cp27-win_amd64')
assert not build_selector('cp36-win_amd64')
assert build_selector('cp37-win_amd64')
def test_build_and_skip():
build_selector = BuildSelector(build_config="cp36-* cp37-macosx* *-manylinux1*", skip_config="cp27-* cp37-manylinux1_i686")
assert not build_selector('cp27-manylinux1_x86_64')
assert build_selector('cp36-manylinux1_x86_64')
assert build_selector('cp37-manylinux1_x86_64')
assert not build_selector('cp27-manylinux1_i686')
assert build_selector('cp36-manylinux1_i686')
assert not build_selector('cp37-manylinux1_i686')
assert not build_selector('cp27-macosx_10_6_intel')
assert build_selector('cp36-macosx_10_6_intel')
assert build_selector('cp37-macosx_10_6_intel')
assert not build_selector('cp27-win32')
assert build_selector('cp36-win32')
assert not build_selector('cp37-win32')
assert not build_selector('cp27-win_amd64')
assert build_selector('cp36-win_amd64')
assert not build_selector('cp37-win_amd64')
+6 -2
View File
@@ -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():
+59
View File
@@ -0,0 +1,59 @@
import sys
import os
import subprocess
import pytest
from cibuildwheel.__main__ import main
from cibuildwheel import windows, linux, macos
def not_call_mock(*args, **kwargs):
raise RuntimeError("This should never be called")
def apply_mock_protection(monkeypatch):
monkeypatch.setattr(subprocess, "Popen", not_call_mock)
monkeypatch.setattr(windows, "urlopen", not_call_mock)
monkeypatch.setattr(windows, "build", not_call_mock)
monkeypatch.setattr(linux, "build", not_call_mock)
monkeypatch.setattr(macos, "build", not_call_mock)
def test_unknown_platform_non_ci(monkeypatch, capsys, tmp_path):
monkeypatch.setattr(os, 'environ', {})
monkeypatch.setattr(sys, "argv", ["python", str(tmp_path)])
apply_mock_protection(monkeypatch)
with pytest.raises(SystemExit) as exit:
main()
assert exit.value.code == 2
_, err = capsys.readouterr()
assert 'cibuildwheel: Unable to detect platform.' in err
assert "cibuildwheel should run on your CI server" in err
def test_unknown_platform_on_ci(monkeypatch, capsys, tmp_path):
monkeypatch.setattr(os, 'environ', {"CI": "true"})
monkeypatch.setattr(sys, "argv", ["python", str(tmp_path)])
apply_mock_protection(monkeypatch)
monkeypatch.setattr(sys, "platform", "Something")
with pytest.raises(SystemExit) as exit:
main()
_, err = capsys.readouterr()
assert exit.value.code == 2
assert 'cibuildwheel: Unable to detect platform from "sys.platform"' in err
def test_unknown_platform(monkeypatch, capsys, tmp_path):
monkeypatch.setattr(os, 'environ', {"CIBW_PLATFORM": "Something"})
monkeypatch.setattr(sys, "argv", ["python", str(tmp_path)])
apply_mock_protection(monkeypatch)
with open(str(tmp_path / "setup.py"), "w") as f:
f.write('from setuptools import setup\nsetup(name="spam", version="0.1.0",)')
with pytest.raises(SystemExit) as exit:
main()
_, err = capsys.readouterr()
assert exit.value.code == 2
assert 'cibuildwheel: Unsupported platform: Something' in err