Merge remote-tracking branch 'origin/master' into macos-universal2
# Conflicts: # cibuildwheel/macos.py # cibuildwheel/util.py
This commit is contained in:
@@ -6,7 +6,7 @@ import traceback
|
|||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from typing import Any, Dict, List, Optional, overload
|
from typing import Any, Dict, List, Optional, Set, overload
|
||||||
|
|
||||||
import cibuildwheel
|
import cibuildwheel
|
||||||
import cibuildwheel.linux
|
import cibuildwheel.linux
|
||||||
@@ -304,13 +304,13 @@ def print_preamble(platform: str, build_options: BuildOptions) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def print_build_identifiers(
|
def print_build_identifiers(
|
||||||
platform: str, build_selector: BuildSelector, architectures: List[Architecture]
|
platform: str, build_selector: BuildSelector, architectures: Set[Architecture]
|
||||||
) -> None:
|
) -> None:
|
||||||
python_configurations: List[Any] = []
|
python_configurations: List[Any] = []
|
||||||
if platform == 'linux':
|
if platform == 'linux':
|
||||||
python_configurations = cibuildwheel.linux.get_python_configurations(build_selector, architectures)
|
python_configurations = cibuildwheel.linux.get_python_configurations(build_selector, architectures)
|
||||||
elif platform == 'windows':
|
elif platform == 'windows':
|
||||||
python_configurations = cibuildwheel.windows.get_python_configurations(build_selector)
|
python_configurations = cibuildwheel.windows.get_python_configurations(build_selector, architectures)
|
||||||
elif platform == 'macos':
|
elif platform == 'macos':
|
||||||
python_configurations = cibuildwheel.macos.get_python_configurations(build_selector, architectures)
|
python_configurations = cibuildwheel.macos.get_python_configurations(build_selector, architectures)
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
from pathlib import Path, PurePath
|
from pathlib import Path, PurePath
|
||||||
from typing import List, NamedTuple
|
from typing import List, NamedTuple, Set
|
||||||
|
|
||||||
from .docker_container import DockerContainer
|
from .docker_container import DockerContainer
|
||||||
from .logger import log
|
from .logger import log
|
||||||
from .util import (
|
from .util import (
|
||||||
Architecture, BuildOptions, BuildSelector, NonPlatformWheelError,
|
Architecture, BuildOptions, BuildSelector, NonPlatformWheelError,
|
||||||
get_build_verbosity_extra_flags, prepare_command,
|
allowed_architectures_check, get_build_verbosity_extra_flags, prepare_command,
|
||||||
)
|
)
|
||||||
from .typing import PathOrStr
|
from .typing import PathOrStr
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ class PythonConfiguration(NamedTuple):
|
|||||||
|
|
||||||
|
|
||||||
def get_python_configurations(
|
def get_python_configurations(
|
||||||
build_selector: BuildSelector, architectures: List[Architecture]
|
build_selector: BuildSelector, architectures: Set[Architecture]
|
||||||
) -> List[PythonConfiguration]:
|
) -> List[PythonConfiguration]:
|
||||||
python_configurations = [
|
python_configurations = [
|
||||||
PythonConfiguration(version='2.7', identifier='cp27-manylinux_x86_64', path_str='/opt/python/cp27-cp27m'),
|
PythonConfiguration(version='2.7', identifier='cp27-manylinux_x86_64', path_str='/opt/python/cp27-cp27m'),
|
||||||
@@ -61,7 +61,7 @@ def get_python_configurations(
|
|||||||
PythonConfiguration(version='3.9', identifier='cp39-manylinux_s390x', path_str='/opt/python/cp39-cp39'),
|
PythonConfiguration(version='3.9', identifier='cp39-manylinux_s390x', path_str='/opt/python/cp39-cp39'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# return all configurations whose arch is in our `architectures` list,
|
# return all configurations whose arch is in our `architectures` set,
|
||||||
# and match the build/skip rules
|
# and match the build/skip rules
|
||||||
return [
|
return [
|
||||||
c for c in python_configurations
|
c for c in python_configurations
|
||||||
@@ -71,6 +71,8 @@ def get_python_configurations(
|
|||||||
|
|
||||||
|
|
||||||
def build(options: BuildOptions) -> None:
|
def build(options: BuildOptions) -> None:
|
||||||
|
allowed_architectures_check("linux", options)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subprocess.check_output(['docker', '--version'])
|
subprocess.check_output(['docker', '--version'])
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
+5
-10
@@ -5,15 +5,15 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, NamedTuple, Optional, Sequence, Tuple, cast
|
from typing import Any, Dict, List, NamedTuple, Optional, Sequence, Set, Tuple, cast
|
||||||
|
|
||||||
from .environment import ParsedEnvironment
|
from .environment import ParsedEnvironment
|
||||||
from .logger import log
|
from .logger import log
|
||||||
from .util import (Architecture, BuildOptions, BuildSelector, NonPlatformWheelError,
|
from .util import (Architecture, BuildOptions, BuildSelector, NonPlatformWheelError,
|
||||||
download, get_build_verbosity_extra_flags, get_pip_script,
|
download, get_build_verbosity_extra_flags, get_pip_script,
|
||||||
install_certifi_script, prepare_command, unwrap)
|
install_certifi_script, prepare_command, allowed_architectures_check,
|
||||||
|
unwrap)
|
||||||
from .typing import PathOrStr
|
from .typing import PathOrStr
|
||||||
|
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ class PythonConfiguration(NamedTuple):
|
|||||||
|
|
||||||
|
|
||||||
def get_python_configurations(build_selector: BuildSelector,
|
def get_python_configurations(build_selector: BuildSelector,
|
||||||
architectures: List[Architecture]) -> List[PythonConfiguration]:
|
architectures: Set[Architecture]) -> List[PythonConfiguration]:
|
||||||
python_configurations = [
|
python_configurations = [
|
||||||
# CPython
|
# CPython
|
||||||
PythonConfiguration(version='2.7', identifier='cp27-macosx_x86_64', url='https://www.python.org/ftp/python/2.7.18/python-2.7.18-macosx10.9.pkg'),
|
PythonConfiguration(version='2.7', identifier='cp27-macosx_x86_64', url='https://www.python.org/ftp/python/2.7.18/python-2.7.18-macosx10.9.pkg'),
|
||||||
@@ -238,12 +238,7 @@ def setup_python(python_configuration: PythonConfiguration,
|
|||||||
|
|
||||||
|
|
||||||
def build(options: BuildOptions) -> None:
|
def build(options: BuildOptions) -> None:
|
||||||
allowed_archs = {Architecture.x86_64, Architecture.universal2, Architecture.arm64}
|
allowed_architectures_check("macos", options)
|
||||||
if any(a not in allowed_archs for a in options.architectures):
|
|
||||||
raise ValueError(textwrap.dedent(f'''
|
|
||||||
Invalid archs option {[a.value for a in options.architectures]}. macOS only supports
|
|
||||||
these architectures: {', '.join(a.value for a in allowed_archs)}.
|
|
||||||
'''))
|
|
||||||
|
|
||||||
temp_dir = Path(tempfile.mkdtemp(prefix='cibuildwheel'))
|
temp_dir = Path(tempfile.mkdtemp(prefix='cibuildwheel'))
|
||||||
built_wheel_dir = temp_dir / 'built_wheel'
|
built_wheel_dir = temp_dir / 'built_wheel'
|
||||||
|
|||||||
+55
-11
@@ -2,19 +2,26 @@ import os
|
|||||||
import platform as platform_module
|
import platform as platform_module
|
||||||
import re
|
import re
|
||||||
import ssl
|
import ssl
|
||||||
|
import sys
|
||||||
|
import functools
|
||||||
import textwrap
|
import textwrap
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from typing import Dict, List, NamedTuple, Optional
|
from typing import Dict, List, NamedTuple, Optional, Set
|
||||||
|
|
||||||
import certifi
|
import certifi
|
||||||
|
|
||||||
from .environment import ParsedEnvironment
|
from .environment import ParsedEnvironment
|
||||||
from .typing import PathOrStr
|
from .typing import PathOrStr
|
||||||
|
|
||||||
|
if sys.version_info < (3, 8):
|
||||||
|
from typing_extensions import Literal
|
||||||
|
else:
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
|
||||||
def prepare_command(command: str, **kwargs: PathOrStr) -> str:
|
def prepare_command(command: str, **kwargs: PathOrStr) -> str:
|
||||||
'''
|
'''
|
||||||
@@ -124,7 +131,10 @@ class DependencyConstraints:
|
|||||||
return f'{self.__class__.__name__}{self.base_file_path!r})'
|
return f'{self.__class__.__name__}{self.base_file_path!r})'
|
||||||
|
|
||||||
|
|
||||||
|
@functools.total_ordering
|
||||||
class Architecture(Enum):
|
class Architecture(Enum):
|
||||||
|
value: str
|
||||||
|
|
||||||
# mac/linux archs
|
# mac/linux archs
|
||||||
x86_64 = 'x86_64'
|
x86_64 = 'x86_64'
|
||||||
|
|
||||||
@@ -142,31 +152,35 @@ class Architecture(Enum):
|
|||||||
x86 = 'x86'
|
x86 = 'x86'
|
||||||
AMD64 = 'AMD64'
|
AMD64 = 'AMD64'
|
||||||
|
|
||||||
|
# Allow this to be sorted
|
||||||
|
def __lt__(self, other: "Architecture") -> bool:
|
||||||
|
return self.value < other.value
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_config(config: str, platform: str) -> 'List[Architecture]':
|
def parse_config(config: str, platform: str) -> 'Set[Architecture]':
|
||||||
result = []
|
result = set()
|
||||||
for arch_str in re.split(r'[\s,]+', config):
|
for arch_str in re.split(r'[\s,]+', config):
|
||||||
if arch_str == 'auto':
|
if arch_str == 'auto':
|
||||||
result += Architecture.auto_archs(platform=platform)
|
result |= Architecture.auto_archs(platform=platform)
|
||||||
else:
|
else:
|
||||||
result.append(Architecture(arch_str))
|
result.add(Architecture(arch_str))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def auto_archs(platform: str) -> 'List[Architecture]':
|
def auto_archs(platform: str) -> 'Set[Architecture]':
|
||||||
native_architecture = Architecture(platform_module.machine())
|
native_architecture = Architecture(platform_module.machine())
|
||||||
result = [native_architecture]
|
result = {native_architecture}
|
||||||
|
|
||||||
if platform == 'linux' and native_architecture == Architecture.x86_64:
|
if platform == 'linux' and native_architecture == Architecture.x86_64:
|
||||||
# x86_64 machines can run i686 docker containers
|
# x86_64 machines can run i686 docker containers
|
||||||
result.append(Architecture.i686)
|
result.add(Architecture.i686)
|
||||||
|
|
||||||
if platform == 'windows' and native_architecture == Architecture.AMD64:
|
if platform == 'windows' and native_architecture == Architecture.AMD64:
|
||||||
result.append(Architecture.x86)
|
result.add(Architecture.x86)
|
||||||
|
|
||||||
if platform == 'macos' and native_architecture == Architecture.arm64:
|
if platform == 'macos' and native_architecture == Architecture.arm64:
|
||||||
# arm64 can build and test both archs of a universal2 wheel.
|
# arm64 can build and test both archs of a universal2 wheel.
|
||||||
result.append(Architecture.universal2)
|
result.add(Architecture.universal2)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -175,7 +189,7 @@ class BuildOptions(NamedTuple):
|
|||||||
package_dir: Path
|
package_dir: Path
|
||||||
output_dir: Path
|
output_dir: Path
|
||||||
build_selector: BuildSelector
|
build_selector: BuildSelector
|
||||||
architectures: List[Architecture]
|
architectures: Set[Architecture]
|
||||||
environment: ParsedEnvironment
|
environment: ParsedEnvironment
|
||||||
before_all: str
|
before_all: str
|
||||||
before_build: Optional[str]
|
before_build: Optional[str]
|
||||||
@@ -244,6 +258,36 @@ def detect_ci_provider() -> Optional[CIProvider]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
PRETTY_NAMES = {'linux': 'Linux', 'macos': 'macOS', 'windows': 'Windows'}
|
||||||
|
|
||||||
|
ALLOWED_ARCHITECTURES = {
|
||||||
|
'linux': {Architecture.x86_64, Architecture.i686, Architecture.aarch64, Architecture.ppc64le, Architecture.s390x},
|
||||||
|
'macos': {Architecture.x86_64},
|
||||||
|
'windows': {Architecture.AMD64, Architecture.x86},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def allowed_architectures_check(
|
||||||
|
name: Literal['linux', 'macos', 'windows'],
|
||||||
|
options: BuildOptions,
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
allowed_architectures = ALLOWED_ARCHITECTURES[name]
|
||||||
|
|
||||||
|
msg = f'{PRETTY_NAMES[name]} only supports {sorted(allowed_architectures)} at the moment.'
|
||||||
|
|
||||||
|
if name != 'linux':
|
||||||
|
msg += ' If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead.'
|
||||||
|
|
||||||
|
if not options.architectures <= allowed_architectures:
|
||||||
|
msg = f'Invalid archs option {options.architectures}. ' + msg
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
if not options.architectures:
|
||||||
|
msg = 'Empty archs option set. ' + msg
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
def unwrap(text: str) -> str:
|
def unwrap(text: str) -> str:
|
||||||
'''
|
'''
|
||||||
Unwraps multi-line text to a single line
|
Unwraps multi-line text to a single line
|
||||||
|
|||||||
+14
-12
@@ -3,9 +3,8 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, NamedTuple, Optional, Sequence
|
from typing import Dict, List, NamedTuple, Optional, Sequence, Set
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
import toml
|
import toml
|
||||||
@@ -14,7 +13,7 @@ from .environment import ParsedEnvironment
|
|||||||
from .logger import log
|
from .logger import log
|
||||||
from .util import (Architecture, BuildOptions, BuildSelector, NonPlatformWheelError,
|
from .util import (Architecture, BuildOptions, BuildSelector, NonPlatformWheelError,
|
||||||
download, get_build_verbosity_extra_flags, get_pip_script,
|
download, get_build_verbosity_extra_flags, get_pip_script,
|
||||||
prepare_command)
|
prepare_command, allowed_architectures_check)
|
||||||
from .typing import PathOrStr
|
from .typing import PathOrStr
|
||||||
|
|
||||||
IS_RUNNING_ON_AZURE = Path('C:\\hostedtoolcache').exists()
|
IS_RUNNING_ON_AZURE = Path('C:\\hostedtoolcache').exists()
|
||||||
@@ -48,7 +47,12 @@ class PythonConfiguration(NamedTuple):
|
|||||||
url: Optional[str]
|
url: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfiguration]:
|
def get_python_configurations(build_selector: BuildSelector, architectures: Set[Architecture]) -> List[PythonConfiguration]:
|
||||||
|
map_arch = {
|
||||||
|
'32': Architecture.x86,
|
||||||
|
'64': Architecture.AMD64,
|
||||||
|
}
|
||||||
|
|
||||||
python_configurations = [
|
python_configurations = [
|
||||||
# CPython
|
# CPython
|
||||||
PythonConfiguration(version='2.7.18', arch='32', identifier='cp27-win32', url=None),
|
PythonConfiguration(version='2.7.18', arch='32', identifier='cp27-win32', url=None),
|
||||||
@@ -75,7 +79,10 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
|
|||||||
python_configurations = [c for c in python_configurations if not c.version.startswith('2.7')]
|
python_configurations = [c for c in python_configurations if not c.version.startswith('2.7')]
|
||||||
|
|
||||||
# skip builds as required
|
# skip builds as required
|
||||||
python_configurations = [c for c in python_configurations if build_selector(c.identifier)]
|
python_configurations = [
|
||||||
|
c for c in python_configurations
|
||||||
|
if build_selector(c.identifier) and map_arch[c.arch] in architectures
|
||||||
|
]
|
||||||
|
|
||||||
return python_configurations
|
return python_configurations
|
||||||
|
|
||||||
@@ -202,12 +209,7 @@ def pep_518_cp35_workaround(package_dir: Path, env: Dict[str, str]) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def build(options: BuildOptions) -> None:
|
def build(options: BuildOptions) -> None:
|
||||||
if options.architectures != [Architecture.AMD64, Architecture.x86]:
|
allowed_architectures_check("windows", options)
|
||||||
raise ValueError(textwrap.dedent(f'''
|
|
||||||
Invalid archs option {options.architectures}. Windows only supports 'amd64,x86' for the
|
|
||||||
moment. If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX
|
|
||||||
instead.
|
|
||||||
'''))
|
|
||||||
|
|
||||||
temp_dir = Path(tempfile.mkdtemp(prefix='cibuildwheel'))
|
temp_dir = Path(tempfile.mkdtemp(prefix='cibuildwheel'))
|
||||||
built_wheel_dir = temp_dir / 'built_wheel'
|
built_wheel_dir = temp_dir / 'built_wheel'
|
||||||
@@ -220,7 +222,7 @@ def build(options: BuildOptions) -> None:
|
|||||||
before_all_prepared = prepare_command(options.before_all, project='.', package=options.package_dir)
|
before_all_prepared = prepare_command(options.before_all, project='.', package=options.package_dir)
|
||||||
shell(before_all_prepared, env=env)
|
shell(before_all_prepared, env=env)
|
||||||
|
|
||||||
python_configurations = get_python_configurations(options.build_selector)
|
python_configurations = get_python_configurations(options.build_selector, options.architectures)
|
||||||
|
|
||||||
for config in python_configurations:
|
for config in python_configurations:
|
||||||
log.build_start(config.identifier)
|
log.build_start(config.identifier)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ install_requires =
|
|||||||
bashlex!=0.13
|
bashlex!=0.13
|
||||||
toml
|
toml
|
||||||
certifi
|
certifi
|
||||||
|
typing_extensions; python_version < '3.8'
|
||||||
|
|
||||||
[options.package_data]
|
[options.package_data]
|
||||||
cibuildwheel = resources/*
|
cibuildwheel = resources/*
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ def test_archs_default(platform, intercepted_build_args, monkeypatch):
|
|||||||
build_options = intercepted_build_args.args[0]
|
build_options = intercepted_build_args.args[0]
|
||||||
|
|
||||||
if platform == 'linux':
|
if platform == 'linux':
|
||||||
assert build_options.architectures == [Architecture.x86_64, Architecture.i686]
|
assert build_options.architectures == {Architecture.x86_64, Architecture.i686}
|
||||||
else:
|
else:
|
||||||
assert build_options.architectures == [Architecture.x86_64]
|
assert build_options.architectures == {Architecture.x86_64}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('use_env_var', [False, True])
|
@pytest.mark.parametrize('use_env_var', [False, True])
|
||||||
@@ -92,7 +92,7 @@ def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_v
|
|||||||
main()
|
main()
|
||||||
build_options = intercepted_build_args.args[0]
|
build_options = intercepted_build_args.args[0]
|
||||||
|
|
||||||
assert build_options.architectures == [Architecture.ppc64le]
|
assert build_options.architectures == {Architecture.ppc64le}
|
||||||
|
|
||||||
|
|
||||||
def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch):
|
def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch):
|
||||||
@@ -106,8 +106,8 @@ def test_archs_platform_specific(platform, intercepted_build_args, monkeypatch):
|
|||||||
build_options = intercepted_build_args.args[0]
|
build_options = intercepted_build_args.args[0]
|
||||||
|
|
||||||
if platform == 'linux':
|
if platform == 'linux':
|
||||||
assert build_options.architectures == [Architecture.ppc64le]
|
assert build_options.architectures == {Architecture.ppc64le}
|
||||||
elif platform == 'windows':
|
elif platform == 'windows':
|
||||||
assert build_options.architectures == [Architecture.x86]
|
assert build_options.architectures == {Architecture.x86}
|
||||||
elif platform == 'macos':
|
elif platform == 'macos':
|
||||||
assert build_options.architectures == [Architecture.x86_64]
|
assert build_options.architectures == {Architecture.x86_64}
|
||||||
|
|||||||
Reference in New Issue
Block a user