Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3b2de0489 | ||
|
|
c3565d5025 | ||
|
|
31ac2ba03f | ||
|
|
083ece8bbc | ||
|
|
bdbbf18e43 | ||
|
|
45a7836cc6 | ||
|
|
d5fa5475d4 | ||
|
|
3f6a943b6d | ||
|
|
c7764d239b | ||
|
|
e072e82252 | ||
|
|
cf7f2e18ce | ||
|
|
a2a2a7b382 | ||
|
|
ba22589f6f | ||
|
|
e9bf990fd2 | ||
|
|
db09cfc4a9 | ||
|
|
2c0d6e3db1 | ||
|
|
89c8735719 | ||
|
|
7a2e951f48 | ||
|
|
ff942ad766 | ||
|
|
881cd66fae | ||
|
|
278661df77 | ||
|
|
520daa4c23 | ||
|
|
2679cb7f46 | ||
|
|
56f9a37165 | ||
|
|
5c91340ad0 |
@@ -1,6 +1,6 @@
|
|||||||
This project is licensed under the 'BSD 2-clause license'.
|
This project is licensed under the 'BSD 2-clause license'.
|
||||||
|
|
||||||
Copyright (c) 2016, Tingbot. All rights reserved.
|
Copyright (c) 2017, Joe Rickerby. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ Usage
|
|||||||
- os: osx
|
- os: osx
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- pip install cibuildwheel==0.1.3
|
- pip install cibuildwheel==0.2.0
|
||||||
- cibuildwheel --output-dir wheelhouse
|
- cibuildwheel --output-dir wheelhouse
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ Usage
|
|||||||
|
|
||||||
```
|
```
|
||||||
build_script:
|
build_script:
|
||||||
- pip install cibuildwheel==0.1.3
|
- pip install cibuildwheel==0.2.0
|
||||||
- cibuildwheel --output-dir wheelhouse
|
- cibuildwheel --output-dir wheelhouse
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: "wheelhouse\\*.whl"
|
- path: "wheelhouse\\*.whl"
|
||||||
@@ -132,24 +132,38 @@ Space-separated list of dependencies required for running the tests.
|
|||||||
Example: `pytest`
|
Example: `pytest`
|
||||||
Example: `nose==1.3.7 moto==0.4.31`
|
Example: `nose==1.3.7 moto==0.4.31`
|
||||||
|
|
||||||
| Environment variable: `CIBW_SKIP` | 🔶 coming soon 🔶
|
| Environment variable: `CIBW_BEFORE_BUILD`
|
||||||
| --- | ---
|
| ---
|
||||||
|
|
||||||
Optional.
|
Optional.
|
||||||
|
|
||||||
Space-separated list of builds to skip. Each build has an identifier like `cp27-linux_x86_64` or `cp34-macosx_10_6_intel` - you can list ones to skip here and `cibuildwheel` won't try to build them.
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Example: `{pip} install pybind11`
|
||||||
|
|
||||||
|
Platform-specific variants also available:
|
||||||
|
`CIBW_BEFORE_BUILD_MACOS` | `CIBW_BEFORE_BUILD_WINDOWS` | `CIBW_BEFORE_BUILD_LINUX`
|
||||||
|
|
||||||
|
| 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).
|
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`
|
Python tags look like `cp27` `cp34` `cp35` `cp36`
|
||||||
|
|
||||||
Platform tags look like `macosx_10_6_intel` `linux_x86_64` `linux_i386` `win32` `win_amd64`
|
Platform tags look like `macosx_10_6_intel` `manylinux1_x86_64` `manylinux1_i386` `win32` `win_amd64`
|
||||||
|
|
||||||
You can also use shell-style globbing syntax (as per `fnmatch`)
|
You can also use shell-style globbing syntax (as per `fnmatch`)
|
||||||
|
|
||||||
Example: `cp27-macosx_10_6_intel ` (don't build on Python 2 on Mac)
|
Example: `cp27-macosx_10_6_intel ` (don't build on Python 2 on Mac)
|
||||||
Example: `cp27-win*` (don't build on Python 2.7 on Windows)
|
Example: `cp27-win*` (don't build on Python 2.7 on Windows)
|
||||||
Example: `cp34-*` (don't build on Python 3.4)
|
Example: `cp34-* cp35-*` (don't build on Python 3.4 or Python 3.5)
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
@@ -251,6 +265,7 @@ Credits
|
|||||||
- ⭐️ @matthew-brett for [matthew-brett/multibuild](http://github.com/matthew-brett/multibuild) and [matthew-brett/delocate](http://github.com/matthew-brett/delocate)
|
- ⭐️ @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)
|
- @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`
|
- @ogrisel for [wheelhouse-uploader](https://github.com/ogrisel/wheelhouse-uploader) and `run_with_env.cmd`
|
||||||
|
- @zfrenchee for [help debugging many issues](https://github.com/joerick/cibuildwheel/issues/2)
|
||||||
|
|
||||||
See also
|
See also
|
||||||
--------
|
--------
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
__version__ = '0.2.0'
|
||||||
|
|||||||
+83
-37
@@ -1,7 +1,27 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import argparse, os, subprocess, sys
|
import argparse, os, subprocess, sys, textwrap
|
||||||
|
|
||||||
|
import cibuildwheel
|
||||||
|
import cibuildwheel.linux, cibuildwheel.windows, cibuildwheel.macos
|
||||||
|
from cibuildwheel.util import BuildSkipper
|
||||||
|
|
||||||
|
def get_option_from_environment(option_name, platform=None):
|
||||||
|
'''
|
||||||
|
Returns an option from the environment, optionally scoped by the platform.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
get_option_from_environment('CIBW_COLOR', platform='macos')
|
||||||
|
|
||||||
|
This will return the value of CIBW_COLOR_MACOS if it exists, otherwise the value of
|
||||||
|
CIBW_COLOR.
|
||||||
|
'''
|
||||||
|
if platform:
|
||||||
|
option = os.environ.get('%s_%s' % (option_name, platform.upper()))
|
||||||
|
if option is not None:
|
||||||
|
return option
|
||||||
|
|
||||||
|
return os.environ.get(option_name)
|
||||||
|
|
||||||
from cibuildwheel import linux, windows, macos
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
@@ -29,38 +49,6 @@ def main():
|
|||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
output_dir = args.output_dir
|
|
||||||
test_command = os.environ.get('CIBW_TEST_COMMAND', None)
|
|
||||||
test_requires = os.environ.get('CIBW_TEST_REQUIRES', '').split()
|
|
||||||
project_dir = args.project_dir
|
|
||||||
|
|
||||||
try:
|
|
||||||
project_setup_py = os.path.join(project_dir, 'setup.py')
|
|
||||||
package_name = subprocess.check_output([sys.executable, project_setup_py, '--name'])
|
|
||||||
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)
|
|
||||||
|
|
||||||
package_name = package_name.strip()
|
|
||||||
|
|
||||||
if package_name == '' or package_name == 'UNKNOWN':
|
|
||||||
print('cibuildwheel: Invalid package name "%s". Check your setup.py' % package_name,
|
|
||||||
file=sys.stderr)
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
build_args = dict(
|
|
||||||
project_dir=project_dir,
|
|
||||||
package_name=package_name,
|
|
||||||
output_dir=output_dir,
|
|
||||||
test_command=test_command,
|
|
||||||
test_requires=test_requires
|
|
||||||
)
|
|
||||||
|
|
||||||
if args.platform != 'auto':
|
if args.platform != 'auto':
|
||||||
platform = args.platform
|
platform = args.platform
|
||||||
else:
|
else:
|
||||||
@@ -78,14 +66,72 @@ def main():
|
|||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
exit(2)
|
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()
|
||||||
|
project_dir = args.project_dir
|
||||||
|
before_build = get_option_from_environment('CIBW_BEFORE_BUILD', platform=platform)
|
||||||
|
skip_config = os.environ.get('CIBW_SKIP', '')
|
||||||
|
|
||||||
|
skip = BuildSkipper(skip_config)
|
||||||
|
|
||||||
|
try:
|
||||||
|
project_setup_py = os.path.join(project_dir, 'setup.py')
|
||||||
|
name_output = subprocess.check_output([sys.executable, project_setup_py, '--name'])
|
||||||
|
# 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)
|
||||||
|
exit(2)
|
||||||
|
|
||||||
|
build_options = dict(
|
||||||
|
project_dir=project_dir,
|
||||||
|
package_name=package_name,
|
||||||
|
output_dir=output_dir,
|
||||||
|
test_command=test_command,
|
||||||
|
test_requires=test_requires,
|
||||||
|
before_build=before_build,
|
||||||
|
skip=skip,
|
||||||
|
)
|
||||||
|
|
||||||
|
print_preamble(platform, build_options)
|
||||||
|
|
||||||
if platform == 'linux':
|
if platform == 'linux':
|
||||||
linux.build(**build_args)
|
cibuildwheel.linux.build(**build_options)
|
||||||
elif platform == 'windows':
|
elif platform == 'windows':
|
||||||
windows.build(**build_args)
|
cibuildwheel.windows.build(**build_options)
|
||||||
elif platform == 'macos':
|
elif platform == 'macos':
|
||||||
macos.build(**build_args)
|
cibuildwheel.macos.build(**build_options)
|
||||||
else:
|
else:
|
||||||
raise Exception('Unsupported platform')
|
raise Exception('Unsupported platform')
|
||||||
|
|
||||||
|
def print_preamble(platform, build_options):
|
||||||
|
print(textwrap.dedent('''
|
||||||
|
_ _ _ _ _ _ _
|
||||||
|
___|_| |_ _ _|_| |_| |_ _ _| |_ ___ ___| |
|
||||||
|
| _| | . | | | | | . | | | | | -_| -_| |
|
||||||
|
|___|_|___|___|_|_|___|_____|_|_|___|___|_|
|
||||||
|
'''))
|
||||||
|
|
||||||
|
print('cibuildwheel version %s\n' % cibuildwheel.__version__)
|
||||||
|
|
||||||
|
|
||||||
|
print('Build options:')
|
||||||
|
print(' platform: %r' % platform)
|
||||||
|
for option, value in build_options.items():
|
||||||
|
print(' %s: %r' % (option, value))
|
||||||
|
|
||||||
|
print('\nHere we go!\n')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|||||||
+56
-7
@@ -1,5 +1,7 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import os, subprocess
|
import os, subprocess
|
||||||
|
from collections import namedtuple
|
||||||
|
from .util import prepare_command
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from shlex import quote as shlex_quote
|
from shlex import quote as shlex_quote
|
||||||
@@ -7,23 +9,62 @@ except ImportError:
|
|||||||
from pipes import quote as shlex_quote
|
from pipes import quote as shlex_quote
|
||||||
|
|
||||||
|
|
||||||
def build(project_dir, package_name, output_dir, test_command, test_requires):
|
def build(project_dir, package_name, output_dir, test_command, test_requires, before_build, skip):
|
||||||
for docker_image in ['quay.io/pypa/manylinux1_x86_64', 'quay.io/pypa/manylinux1_i686']:
|
PythonConfiguration = namedtuple('PythonConfiguration', ['identifier', 'path'])
|
||||||
|
python_configurations = [
|
||||||
|
PythonConfiguration(identifier='cp26-manylinux1_x86_64', path='/opt/python/cp26-cp26m'),
|
||||||
|
PythonConfiguration(identifier='cp26-manylinux1_x86_64', path='/opt/python/cp26-cp26mu'),
|
||||||
|
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='cp26-manylinux1_i686', path='/opt/python/cp26-cp26m'),
|
||||||
|
PythonConfiguration(identifier='cp26-manylinux1_i686', path='/opt/python/cp26-cp26mu'),
|
||||||
|
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)]
|
||||||
|
|
||||||
|
platforms = [
|
||||||
|
('manylinux1_x86_64', 'quay.io/pypa/manylinux1_x86_64'),
|
||||||
|
('manylinux1_i686', 'quay.io/pypa/manylinux1_i686'),
|
||||||
|
]
|
||||||
|
|
||||||
|
for platform_tag, docker_image in platforms:
|
||||||
|
platform_configs = [c for c in python_configurations if c.identifier.endswith(platform_tag)]
|
||||||
|
|
||||||
bash_script = '''
|
bash_script = '''
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o xtrace
|
set -o xtrace
|
||||||
cd /project
|
cd /project
|
||||||
|
|
||||||
for PYBIN in /opt/python/*/bin; do
|
for PYBIN in {pybin_paths}; do
|
||||||
|
if [ ! -z {before_build} ]; then
|
||||||
|
PATH=$PYBIN:$PATH sh -c {before_build}
|
||||||
|
fi
|
||||||
|
|
||||||
"$PYBIN/pip" wheel . -w /tmp/linux_wheels
|
"$PYBIN/pip" wheel . -w /tmp/linux_wheels
|
||||||
done
|
done
|
||||||
|
|
||||||
for whl in /tmp/linux_wheels/*.whl; do
|
for whl in /tmp/linux_wheels/*.whl; do
|
||||||
auditwheel repair "$whl" -w /output
|
if [[ "$whl" == *none-any.whl ]]; then
|
||||||
|
# pure python wheel - just copy to the output
|
||||||
|
cp "$whl" /output
|
||||||
|
else
|
||||||
|
auditwheel repair "$whl" -w /output
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Install packages and test
|
# Install packages and test
|
||||||
for PYBIN in /opt/python/*/bin/; do
|
for PYBIN in {pybin_paths}; do
|
||||||
# Install the wheel we just built
|
# Install the wheel we just built
|
||||||
"$PYBIN/pip" install {package_name} --no-index -f /output
|
"$PYBIN/pip" install {package_name} --no-index -f /output
|
||||||
|
|
||||||
@@ -34,13 +75,21 @@ def build(project_dir, package_name, output_dir, test_command, test_requires):
|
|||||||
|
|
||||||
# Run the tests from a different directory
|
# Run the tests from a different directory
|
||||||
if [ ! -z {test_command} ]; then
|
if [ ! -z {test_command} ]; then
|
||||||
(cd "$HOME" && export PATH=$PYBIN:$PATH && sh -c {test_command})
|
pushd $HOME
|
||||||
|
PATH=$PYBIN:$PATH sh -c {test_command}
|
||||||
|
popd
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
'''.format(
|
'''.format(
|
||||||
package_name=package_name,
|
package_name=package_name,
|
||||||
|
pybin_paths=' '.join(c.path+'/bin' for c in platform_configs),
|
||||||
test_requires=' '.join(test_requires),
|
test_requires=' '.join(test_requires),
|
||||||
test_command=shlex_quote(test_command.format(project='/project') if test_command else ''),
|
test_command=shlex_quote(
|
||||||
|
test_command.format(project='/project') if test_command else ''
|
||||||
|
),
|
||||||
|
before_build=shlex_quote(
|
||||||
|
prepare_command(before_build, python='python', pip='pip') if before_build else ''
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
docker_process = subprocess.Popen([
|
docker_process = subprocess.Popen([
|
||||||
|
|||||||
+27
-12
@@ -1,5 +1,5 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import os, subprocess, shlex
|
import os, subprocess, shlex, sys
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from glob import glob
|
from glob import glob
|
||||||
try:
|
try:
|
||||||
@@ -7,14 +7,16 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
from pipes import quote as shlex_quote
|
from pipes import quote as shlex_quote
|
||||||
|
|
||||||
|
from .util import prepare_command
|
||||||
|
|
||||||
def build(project_dir, package_name, output_dir, test_command, test_requires):
|
|
||||||
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'url'])
|
def build(project_dir, package_name, output_dir, test_command, test_requires, before_build, skip):
|
||||||
|
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'identifier', 'url'])
|
||||||
python_configurations = [
|
python_configurations = [
|
||||||
PythonConfiguration(version='2.7', url='https://www.python.org/ftp/python/2.7.13/python-2.7.13-macosx10.6.pkg'),
|
PythonConfiguration(version='2.7', identifier='cp27-macosx_10_6_intel', url='https://www.python.org/ftp/python/2.7.13/python-2.7.13-macosx10.6.pkg'),
|
||||||
PythonConfiguration(version='3.4', url='https://www.python.org/ftp/python/3.4.4/python-3.4.4-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='3.5', url='https://www.python.org/ftp/python/3.5.3/python-3.5.3-macosx10.6.pkg'),
|
PythonConfiguration(version='3.5', identifier='cp35-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.5.3/python-3.5.3-macosx10.6.pkg'),
|
||||||
PythonConfiguration(version='3.6', url='https://www.python.org/ftp/python/3.6.0/python-3.6.0-macosx10.6.pkg'),
|
PythonConfiguration(version='3.6', identifier='cp36-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.6.0/python-3.6.0-macosx10.6.pkg'),
|
||||||
]
|
]
|
||||||
|
|
||||||
def shell(args, env=None, cwd=None):
|
def shell(args, env=None, cwd=None):
|
||||||
@@ -23,6 +25,10 @@ def build(project_dir, package_name, output_dir, test_command, test_requires):
|
|||||||
return subprocess.check_call(args, env=env, cwd=cwd)
|
return subprocess.check_call(args, env=env, cwd=cwd)
|
||||||
|
|
||||||
for config in python_configurations:
|
for config in python_configurations:
|
||||||
|
if skip(config.identifier):
|
||||||
|
print('cibuildwheel: Skipping build %s' % config.identifier, file=sys.stderr)
|
||||||
|
continue
|
||||||
|
|
||||||
# download the pkg
|
# download the pkg
|
||||||
shell(['curl', '-L', '-o', '/tmp/Python.pkg', config.url])
|
shell(['curl', '-L', '-o', '/tmp/Python.pkg', config.url])
|
||||||
# install
|
# install
|
||||||
@@ -43,19 +49,28 @@ def build(project_dir, package_name, output_dir, test_command, test_requires):
|
|||||||
|
|
||||||
# install pip & wheel
|
# install pip & wheel
|
||||||
shell([python, '-m', 'ensurepip', '--upgrade'], env=env)
|
shell([python, '-m', 'ensurepip', '--upgrade'], env=env)
|
||||||
shell([pip, '--version'])
|
shell([pip, '--version'], env=env)
|
||||||
shell([pip, 'install', 'wheel'], env=env)
|
shell([pip, 'install', 'wheel'], env=env)
|
||||||
shell([pip, 'install', 'delocate'], env=env)
|
shell([pip, 'install', 'delocate'], env=env)
|
||||||
|
|
||||||
|
# run the before_build command
|
||||||
|
if before_build:
|
||||||
|
before_build_prepared = prepare_command(before_build, python=python, pip=pip)
|
||||||
|
shell(shlex.split(before_build_prepared), env=env)
|
||||||
|
|
||||||
# build the wheel to temp dir
|
# build the wheel to temp dir
|
||||||
temp_wheel_dir = '/tmp/tmpwheel%s' % config.version
|
temp_wheel_dir = '/tmp/tmpwheel%s' % config.version
|
||||||
shell([pip, 'wheel', project_dir, '-w', temp_wheel_dir], env=env)
|
shell([pip, 'wheel', project_dir, '-w', temp_wheel_dir], env=env)
|
||||||
temp_wheel = glob(temp_wheel_dir+'/*.whl')[0]
|
temp_wheel = glob(temp_wheel_dir+'/*.whl')[0]
|
||||||
|
|
||||||
# list the dependencies
|
if temp_wheel.endswith('none-any.whl'):
|
||||||
shell(['delocate-listdeps', temp_wheel], env=env)
|
# pure python wheel - just copy to output_dir
|
||||||
# rebuild the wheel with shared libraries included and place in output dir
|
shell(['cp', temp_wheel, output_dir], env=env)
|
||||||
shell(['delocate-wheel', '-w', output_dir, temp_wheel], env=env)
|
else:
|
||||||
|
# list the dependencies
|
||||||
|
shell(['delocate-listdeps', temp_wheel], env=env)
|
||||||
|
# rebuild the wheel with shared libraries included and place in output dir
|
||||||
|
shell(['delocate-wheel', '-w', output_dir, temp_wheel], env=env)
|
||||||
|
|
||||||
# install the wheel
|
# install the wheel
|
||||||
shell([pip, 'install', package_name, '--no-index', '--find-links', output_dir], env=env)
|
shell([pip, 'install', package_name, '--no-index', '--find-links', output_dir], env=env)
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
from fnmatch import fnmatch
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_command(command, python, pip):
|
||||||
|
'''
|
||||||
|
Preprocesses a command by expanding variables like {python} or {pip}.
|
||||||
|
|
||||||
|
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.
|
||||||
|
'''
|
||||||
|
return command.format(python=python, pip=pip)
|
||||||
|
|
||||||
|
|
||||||
|
class BuildSkipper(object):
|
||||||
|
def __init__(self, skip_config):
|
||||||
|
self.patterns = skip_config.split()
|
||||||
|
|
||||||
|
def __call__(self, build_id):
|
||||||
|
return any(fnmatch(build_id, pattern) for pattern in self.patterns)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return 'BuildSkipper(%r)' % ' '.join(self.patterns)
|
||||||
+24
-13
@@ -1,9 +1,11 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import os, tempfile, subprocess, urllib2
|
import os, tempfile, subprocess, urllib2, sys
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
from .util import prepare_command
|
||||||
|
|
||||||
def build(project_dir, package_name, output_dir, test_command, test_requires):
|
|
||||||
|
def build(project_dir, package_name, output_dir, test_command, test_requires, before_build, skip):
|
||||||
# run_with_env is a cmd file that sets the right environment variables to
|
# 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')
|
run_with_env = os.path.join(tempfile.gettempdir(), 'appveyor_run_with_env.cmd')
|
||||||
if not os.path.exists(run_with_env):
|
if not os.path.exists(run_with_env):
|
||||||
@@ -17,21 +19,25 @@ def build(project_dir, package_name, output_dir, test_command, test_requires):
|
|||||||
args = ['cmd', '/E:ON', '/V:ON', '/C', run_with_env] + args
|
args = ['cmd', '/E:ON', '/V:ON', '/C', run_with_env] + args
|
||||||
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
|
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
|
||||||
|
|
||||||
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'path'])
|
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier', 'path'])
|
||||||
python_configurations = [
|
python_configurations = [
|
||||||
PythonConfiguration(version='2.7.x', arch="32", path='C:\Python27'),
|
PythonConfiguration(version='2.7.x', arch="32", identifier='cp27-win32', path='C:\Python27'),
|
||||||
PythonConfiguration(version='2.7.x', arch="64", path='C:\Python27-x64'),
|
PythonConfiguration(version='2.7.x', arch="64", identifier='cp27-win_amd64', path='C:\Python27-x64'),
|
||||||
PythonConfiguration(version='3.3.x', arch="32", path='C:\Python33'),
|
PythonConfiguration(version='3.3.x', arch="32", identifier='cp33-win32', path='C:\Python33'),
|
||||||
PythonConfiguration(version='3.3.x', arch="64", path='C:\Python33-x64'),
|
PythonConfiguration(version='3.3.x', arch="64", identifier='cp33-win_amd64', path='C:\Python33-x64'),
|
||||||
PythonConfiguration(version='3.4.x', arch="32", path='C:\Python34'),
|
PythonConfiguration(version='3.4.x', arch="32", identifier='cp34-win32', path='C:\Python34'),
|
||||||
PythonConfiguration(version='3.4.x', arch="64", path='C:\Python34-x64'),
|
PythonConfiguration(version='3.4.x', arch="64", identifier='cp34-win_amd64', path='C:\Python34-x64'),
|
||||||
PythonConfiguration(version='3.5.x', arch="32", path='C:\Python35'),
|
PythonConfiguration(version='3.5.x', arch="32", identifier='cp35-win32', path='C:\Python35'),
|
||||||
PythonConfiguration(version='3.5.x', arch="64", path='C:\Python35-x64'),
|
PythonConfiguration(version='3.5.x', arch="64", identifier='cp35-win_amd64', path='C:\Python35-x64'),
|
||||||
PythonConfiguration(version='3.6.x', arch="32", path='C:\Python36'),
|
PythonConfiguration(version='3.6.x', arch="32", identifier='cp36-win32', path='C:\Python36'),
|
||||||
PythonConfiguration(version='3.6.x', arch="64", path='C:\Python36-x64'),
|
PythonConfiguration(version='3.6.x', arch="64", identifier='cp36-win_amd64', path='C:\Python36-x64'),
|
||||||
]
|
]
|
||||||
|
|
||||||
for config in python_configurations:
|
for config in python_configurations:
|
||||||
|
if skip(config.identifier):
|
||||||
|
print('cibuildwheel: Skipping build %s' % config.identifier, file=sys.stderr)
|
||||||
|
continue
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
# set up environment variables for run_with_env
|
# set up environment variables for run_with_env
|
||||||
env['PYTHON_VERSION'] = config.version
|
env['PYTHON_VERSION'] = config.version
|
||||||
@@ -51,6 +57,11 @@ def build(project_dir, package_name, output_dir, test_command, test_requires):
|
|||||||
env=env)
|
env=env)
|
||||||
shell(['pip', 'install', 'wheel'], env=env)
|
shell(['pip', 'install', 'wheel'], env=env)
|
||||||
|
|
||||||
|
# run the before_build command
|
||||||
|
if before_build:
|
||||||
|
before_build_prepared = prepare_command(before_build, python='python', pip='pip')
|
||||||
|
shell([before_build_prepared], env=env)
|
||||||
|
|
||||||
# build the wheel
|
# build the wheel
|
||||||
shell(['pip', 'wheel', project_dir, '-w', output_dir], env=env)
|
shell(['pip', 'wheel', project_dir, '-w', output_dir], env=env)
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 0.1.3
|
current_version = 0.2.0
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
message = Bump version
|
message = Bump version
|
||||||
|
|
||||||
[bumpversion:file:setup.py]
|
[bumpversion:file:setup.py]
|
||||||
|
|
||||||
|
[bumpversion:file:cibuildwheel/__init__.py]
|
||||||
|
|
||||||
[bumpversion:file:README.md]
|
[bumpversion:file:README.md]
|
||||||
search = cibuildwheel=={current_version}
|
search = cibuildwheel=={current_version}
|
||||||
replace = cibuildwheel=={new_version}
|
replace = cibuildwheel=={new_version}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ except ImportError:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='cibuildwheel',
|
name='cibuildwheel',
|
||||||
version='0.1.3',
|
version='0.2.0',
|
||||||
description="Build Python wheels on CI with minimal configuration.",
|
description="Build Python wheels on CI with minimal configuration.",
|
||||||
long_description='For readme please see http://github.com/joerick/cibuildwheel',
|
long_description='For readme please see http://github.com/joerick/cibuildwheel',
|
||||||
author="Joe Rickerby",
|
author="Joe Rickerby",
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"CIBW_BEFORE_BUILD": "{python} -c \"import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)\"",
|
||||||
|
"CIBW_BEFORE_BUILD_WINDOWS": "{python} -c \"import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)\""
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
from setuptools import setup, Extension
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if sys.argv[-1] != '--name':
|
||||||
|
# assert that the Python version as written to version.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
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="spam",
|
||||||
|
ext_modules=[Extension('spam', sources=['spam.c'])],
|
||||||
|
version="0.1.0",
|
||||||
|
)
|
||||||
@@ -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,2 @@
|
|||||||
|
3.6.0 (default, Feb 7 2017, 23:55:32)
|
||||||
|
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"CIBW_SKIP": "cp26-* cp33-*"
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
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",
|
||||||
|
)
|
||||||
@@ -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,2 @@
|
|||||||
|
3.6.0 (default, Feb 7 2017, 23:55:32)
|
||||||
|
[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]
|
||||||
Reference in New Issue
Block a user