2017-03-19 20:57:51 +00:00
from __future__ import print_function
2018-04-08 19:11:38 +01:00
import argparse , os , subprocess , sys , textwrap
2017-03-19 20:57:51 +00:00
2017-04-13 15:02:04 +01:00
import cibuildwheel
import cibuildwheel.linux , cibuildwheel.windows , cibuildwheel.macos
2017-09-01 13:33:29 +01:00
from cibuildwheel.environment import parse_environment , EnvironmentParseError
2018-09-16 15:16:30 +02:00
from cibuildwheel.util import BuildSelector , Unbuffered
2017-03-19 20:57:51 +00:00
2018-07-05 09:58:05 +01:00
def get_option_from_environment ( option_name , platform = None , default = None ):
2017-04-10 21:42:12 +01:00
'''
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
2018-07-05 09:58:05 +01:00
return os . environ . get ( option_name , default )
2017-04-10 21:42:12 +01:00
2017-03-19 20:57:51 +00:00
def main ():
parser = argparse . ArgumentParser (
description = 'Build wheels for all the platforms.' ,
epilog = ( 'Most options are supplied via environment variables. '
'See https://github.com/joerick/cibuildwheel#options for info.' ))
parser . add_argument ( '--platform' ,
choices = [ 'auto' , 'linux' , 'macos' , 'windows' ],
2017-03-23 11:19:14 +00:00
default = os . environ . get ( 'CIBW_PLATFORM' , 'auto' ),
2017-03-19 20:57:51 +00:00
help = ( '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]. Default: auto.' ))
parser . add_argument ( '--output-dir' ,
default = os . environ . get ( 'CIBW_OUTPUT_DIR' , 'wheelhouse' ),
help = 'Destination folder for the wheels.' )
parser . add_argument ( 'project_dir' ,
default = '.' ,
nargs = '?' ,
help = ( 'Path to the project that you want wheels for. Default: the current '
'directory.' ))
args = parser . parse_args ()
2017-04-10 21:42:12 +01:00
if args . platform != 'auto' :
platform = args . platform
else :
2018-09-05 04:15:32 -04:00
platform = None
2017-04-10 21:42:12 +01:00
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'
2017-09-10 22:02:36 +01:00
elif 'BITRISE_BUILD_NUMBER' in os . environ :
platform = 'macos'
2018-09-05 04:15:32 -04:00
elif os . environ . get ( 'CIRCLECI' ):
if sys . platform . startswith ( 'linux' ):
platform = 'linux'
elif sys . platform . startswith ( 'darwin' ):
platform = 'macos'
if platform is None :
2017-06-27 18:18:20 +01:00
print ( 'cibuildwheel: Unable to detect platform. cibuildwheel should run on your CI server, '
2018-09-05 04:15:32 -04:00
'Travis CI, Appveyor, and CircleCI are supported. You can run on your development '
2017-04-10 21:42:12 +01:00
'machine using the --platform argument. Check --help output for more '
'information.' ,
file = sys . stderr )
exit ( 2 )
2017-03-19 20:57:51 +00:00
output_dir = args . output_dir
2018-07-05 09:58:05 +01:00
test_command = get_option_from_environment ( 'CIBW_TEST_COMMAND' , platform = platform )
test_requires = get_option_from_environment ( 'CIBW_TEST_REQUIRES' , platform = platform , default = '' ) . split ()
2017-03-19 20:57:51 +00:00
project_dir = args . project_dir
2017-04-10 21:42:12 +01:00
before_build = get_option_from_environment ( 'CIBW_BEFORE_BUILD' , platform = platform )
2018-07-05 09:58:05 +01:00
build_verbosity = get_option_from_environment ( 'CIBW_BUILD_VERBOSITY' , platform = platform , default = '' )
2018-09-16 15:16:30 +02:00
build_config , skip_config = os . environ . get ( 'CIBW_BUILD' , '*' ), os . environ . get ( 'CIBW_SKIP' , '' )
2018-07-05 09:58:05 +01:00
environment_config = get_option_from_environment ( 'CIBW_ENVIRONMENT' , platform = platform , default = '' )
2017-07-24 22:39:37 +01:00
2018-04-08 21:24:08 +02:00
try :
build_verbosity = min ( 3 , max ( - 3 , int ( build_verbosity )))
except ValueError :
build_verbosity = 0
2017-09-01 13:33:29 +01:00
try :
environment = parse_environment ( environment_config )
except ( EnvironmentParseError , ValueError ) as e :
2017-09-06 19:18:28 +01:00
print ( 'cibuildwheel: Malformed environment option " %s "' % environment_config , file = sys . stderr )
2017-09-01 13:33:29 +01:00
import traceback
traceback . print_exc ( None , sys . stderr )
exit ( 2 )
2017-04-11 22:57:42 +01:00
2018-09-16 22:49:38 +02:00
build_selector = BuildSelector ( build_config , skip_config )
2017-03-19 20:57:51 +00:00
2017-08-22 21:41:13 +02:00
# Add CIBUILDWHEEL environment variable
# This needs to be passed on to the docker container in linux.py
os . environ [ 'CIBUILDWHEEL' ] = '1'
2018-11-29 23:20:38 +01:00
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 )
2018-11-29 02:44:19 +00:00
exit ( 2 )
2017-04-13 15:02:04 +01:00
build_options = dict (
2017-03-19 20:57:51 +00:00
project_dir = project_dir ,
output_dir = output_dir ,
test_command = test_command ,
2017-04-10 21:42:12 +01:00
test_requires = test_requires ,
before_build = before_build ,
2018-04-08 21:24:08 +02:00
build_verbosity = build_verbosity ,
2018-09-16 22:49:38 +02:00
build_selector = build_selector ,
2017-07-24 22:39:37 +01:00
environment = environment ,
2017-03-19 20:57:51 +00:00
)
2017-11-19 23:18:10 +01:00
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 )
build_options . update (
manylinux1_images = { 'x86_64' : manylinux1_x86_64_image , 'i686' : manylinux1_i686_image },
)
elif platform == 'macos' :
pass
elif platform == 'windows' :
pass
2018-08-02 12:04:39 +02:00
# 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 )
2017-04-13 15:02:04 +01:00
print_preamble ( platform , build_options )
2017-07-02 18:02:27 -05:00
if not os . path . exists ( output_dir ):
2017-08-31 09:49:57 +02:00
os . makedirs ( output_dir )
2017-07-02 18:02:27 -05:00
2017-03-19 20:57:51 +00:00
if platform == 'linux' :
2017-11-19 23:18:10 +01:00
cibuildwheel . linux . build ( ** build_options )
2017-03-19 20:57:51 +00:00
elif platform == 'windows' :
2017-04-13 15:02:04 +01:00
cibuildwheel . windows . build ( ** build_options )
2017-03-19 20:57:51 +00:00
elif platform == 'macos' :
2017-04-13 15:02:04 +01:00
cibuildwheel . macos . build ( ** build_options )
2017-03-19 20:57:51 +00:00
else :
2017-03-19 21:27:29 +00:00
raise Exception ( 'Unsupported platform' )
2017-03-19 20:57:51 +00:00
2017-04-13 15:02:04 +01:00
def print_preamble ( platform , build_options ):
print ( textwrap . dedent ( '''
_ _ _ _ _ _ _
___|_| |_ _ _|_| |_| |_ _ _| |_ ___ ___| |
| _| | . | | | | | . | | | | | -_| -_| |
|___|_|___|___|_|_|___|_____|_|_|___|___|_|
''' ))
print ( 'cibuildwheel version %s \n ' % cibuildwheel . __version__ )
print ( 'Build options:' )
print ( ' platform: %r ' % platform )
2018-11-30 00:02:18 +01:00
for option , value in sorted ( build_options . items ()):
2017-04-13 15:02:04 +01:00
print ( ' %s : %r ' % ( option , value ))
2018-04-08 18:42:47 +01:00
warnings = detect_warnings ( platform , build_options )
if warnings :
print ( ' \n Warnings:' )
for warning in warnings :
print ( ' ' + warning )
2017-04-13 15:02:04 +01:00
print ( ' \n Here we go! \n ' )
2018-04-08 18:42:47 +01:00
def detect_warnings ( platform , build_options ):
warnings = []
# warn about deprecated {python} and {pip}
for option_name in [ 'test_command' , 'before_build' ]:
2018-04-08 23:38:54 +01:00
option_value = build_options . get ( option_name )
2018-04-08 18:42:47 +01:00
2018-04-08 23:38:54 +01:00
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." )
2018-04-08 18:42:47 +01:00
return warnings
2017-03-19 20:57:51 +00:00
if __name__ == '__main__' :
main ()