Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: configuration support #684

Merged
merged 29 commits into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1d88d5e
feat: configuration support
henryiii May 22, 2021
ff86318
refactor: include manylinux, minor redesign
henryiii May 24, 2021
57ab3c0
"project global" overrides "default platform"
mayeut May 25, 2021
2086d31
fix: add PyPy images
henryiii May 27, 2021
956e148
refactor: remove global
henryiii May 27, 2021
8fd69ef
fix: support tables and arrays
henryiii May 27, 2021
4502917
docs: add pyproject.toml config to docs
henryiii May 27, 2021
d3c89a2
docs: updates based on feedback
henryiii May 31, 2021
93f231d
fix: only join if sensible
henryiii May 31, 2021
d163ef9
refactor: remove manylinux dict
henryiii Jun 1, 2021
e21e983
docs: examples headers and sections on each
henryiii Jun 1, 2021
4bebdb6
feat: support changing the config from the command line
henryiii Jun 1, 2021
9845a4f
fix: use {package}
henryiii Jun 1, 2021
5e05678
tests: add a few tests and mention config one more place
henryiii Jun 2, 2021
d45aa35
Restyle examples tabs to remove indent
joerick Jun 2, 2021
8f221c4
Unrelated docs improvements
joerick Jun 2, 2021
e243ac0
Absorb extra content into the tab
joerick Jun 2, 2021
7dd76d9
Make the tabs smaller and to the right
joerick Jun 2, 2021
4cab971
Copy edits to options
joerick Jun 2, 2021
aedc49e
Fix header ids
joerick Jun 2, 2021
86eaa24
Use fewer [tool.cibuildwheel] headers
joerick Jun 2, 2021
cc2e838
docs: minor additions/fixes
henryiii Jun 3, 2021
26abb41
feat: disallow options on some platforms
henryiii Jun 5, 2021
fe99d04
docs: make the examples a tiny bit more tabby
henryiii Jun 5, 2021
48da604
fix: enforce tables/lists are optionally separate
henryiii Jun 9, 2021
ae5db29
Some unrelated fixes to the other tab styling
joerick Jun 17, 2021
fe2c3d7
Minor fix to tab styling
joerick Jun 17, 2021
21e19b6
Refactor to make code a bit more linear and immutable
joerick Jun 17, 2021
84e33a3
Minor docs changes
joerick Jun 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ Options
| | [`CIBW_TEST_SKIP`](https://cibuildwheel.readthedocs.io/en/stable/options/#test-skip) | Skip running tests on some builds |
| **Other** | [`CIBW_BUILD_VERBOSITY`](https://cibuildwheel.readthedocs.io/en/stable/options/#build-verbosity) | Increase/decrease the output of pip wheel |

These options can be specified in a pyproject.toml file, as well; see [configuration](https://cibuildwheel.readthedocs.io/en/stable/options/#configuration).

Working examples
----------------
Expand Down
157 changes: 62 additions & 95 deletions cibuildwheel/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import traceback
from configparser import ConfigParser
from pathlib import Path
from typing import Dict, List, Optional, Set, Union, overload
from typing import Dict, List, Optional, Set, Union

from packaging.specifiers import SpecifierSet

Expand All @@ -16,6 +16,7 @@
import cibuildwheel.windows
from cibuildwheel.architecture import Architecture, allowed_architectures_check
from cibuildwheel.environment import EnvironmentParseError, parse_environment
from cibuildwheel.options import ConfigOptions
from cibuildwheel.projectfiles import get_requires_python_str
from cibuildwheel.typing import PLATFORMS, PlatformName, assert_never
from cibuildwheel.util import (
Expand All @@ -28,39 +29,16 @@
resources_dir,
)


@overload
def get_option_from_environment(
option_name: str, *, platform: Optional[str] = None, default: str
) -> str:
... # noqa: E704


@overload
def get_option_from_environment(
option_name: str, *, platform: Optional[str] = None, default: None = None
) -> Optional[str]:
... # noqa: E704 E302


def get_option_from_environment(
option_name: str, *, platform: Optional[str] = None, default: Optional[str] = None
) -> Optional[str]: # noqa: E302
"""
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(f"{option_name}_{platform.upper()}")
if option is not None:
return option

return os.environ.get(option_name, default)
MANYLINUX_ARCHS = (
Copy link
Contributor Author

@henryiii henryiii Jun 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect order doesn't matter and this could be a set, but I left it as is, so the ordering would match in the dict it creates. It doesn't logically need to be a set, so this is fine, I think.

"x86_64",
"i686",
"pypy_x86_64",
"aarch64",
"ppc64le",
"s390x",
"pypy_aarch64",
"pypy_i686",
)


def main() -> None:
Expand All @@ -69,8 +47,9 @@ def main() -> None:
parser = argparse.ArgumentParser(
description="Build wheels for all the platforms.",
epilog="""
Most options are supplied via environment variables.
See https://github.com/pypa/cibuildwheel#options for info.
Most options are supplied via environment variables or in
--config-file (pyproject.toml usually). See
https://github.com/pypa/cibuildwheel#options for info.
""",
)

Expand Down Expand Up @@ -104,10 +83,17 @@ def main() -> None:

parser.add_argument(
"--output-dir",
default=os.environ.get("CIBW_OUTPUT_DIR", "wheelhouse"),
help="Destination folder for the wheels.",
)

parser.add_argument(
"--config-file",
help="""
TOML config file for cibuildwheel. Defaults to pyproject.toml, but
can be overridden with this option.
""",
)

parser.add_argument(
"package_dir",
default=".",
Expand Down Expand Up @@ -176,40 +162,40 @@ def main() -> None:
sys.exit(2)

package_dir = Path(args.package_dir)
output_dir = Path(args.output_dir)

if platform == "linux":
repair_command_default = "auditwheel repair -w {dest_dir} {wheel}"
elif platform == "macos":
repair_command_default = "delocate-listdeps {wheel} && delocate-wheel --require-archs {delocate_archs} -w {dest_dir} {wheel}"
elif platform == "windows":
repair_command_default = ""
else:
assert_never(platform)

build_config = os.environ.get("CIBW_BUILD") or "*"
skip_config = os.environ.get("CIBW_SKIP", "")
test_skip = os.environ.get("CIBW_TEST_SKIP", "")
environment_config = get_option_from_environment(
"CIBW_ENVIRONMENT", platform=platform, default=""
)
before_all = get_option_from_environment("CIBW_BEFORE_ALL", platform=platform, default="")
before_build = get_option_from_environment("CIBW_BEFORE_BUILD", platform=platform)
repair_command = get_option_from_environment(
"CIBW_REPAIR_WHEEL_COMMAND", platform=platform, default=repair_command_default
)
dependency_versions = get_option_from_environment(
"CIBW_DEPENDENCY_VERSIONS", platform=platform, default="pinned"
)
test_command = get_option_from_environment("CIBW_TEST_COMMAND", platform=platform)
before_test = get_option_from_environment("CIBW_BEFORE_TEST", 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="")
build_verbosity_str = get_option_from_environment(
"CIBW_BUILD_VERBOSITY", platform=platform, default=""
manylinux_identifiers = {
f"manylinux-{build_platform}-image" for build_platform in MANYLINUX_ARCHS
}
disallow = {
"linux": {"dependency-versions"},
"macos": manylinux_identifiers,
"windows": manylinux_identifiers,
}
options = ConfigOptions(package_dir, args.config_file, platform=platform, disallow=disallow)
output_dir = Path(
args.output_dir
if args.output_dir is not None
else os.environ.get("CIBW_OUTPUT_DIR", "wheelhouse")
)

build_config = options("build", env_plat=False, sep=" ") or "*"
skip_config = options("skip", env_plat=False, sep=" ")
test_skip = options("test-skip", env_plat=False, sep=" ")

archs_config_str = args.archs or options("archs", sep=" ")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny unrelated cleanup - this reads more like the other options, and is clearer - args.archs overrides options, which is rather hidden the way it was written before.


environment_config = options("environment", table={"item": '{k}="{v}"', "sep": " "})
before_all = options("before-all", sep=" && ")
before_build = options("before-build", sep=" && ")
repair_command = options("repair-wheel-command", sep=" && ")

dependency_versions = options("dependency-versions")
test_command = options("test-command", sep=" && ")
before_test = options("before-test", sep=" && ")
test_requires = options("test-requires", sep=" ").split()
test_extras = options("test-extras", sep=",")
build_verbosity_str = options("build-verbosity")

prerelease_pythons = args.prerelease_pythons or cibuildwheel.util.strtobool(
os.environ.get("CIBW_PRERELEASE_PYTHONS", "0")
)
Expand All @@ -218,11 +204,11 @@ def main() -> None:

if not any(package_dir.joinpath(name).exists() for name in package_files):
names = ", ".join(sorted(package_files, reverse=True))
print(
f"cibuildwheel: Could not find any of {{{names}}} at root of package", file=sys.stderr
)
msg = f"cibuildwheel: Could not find any of {{{names}}} at root of package"
print(msg, file=sys.stderr)
sys.exit(2)

# This is not supported in tool.cibuildwheel, as it comes from a standard location.
# Passing this in as an environment variable will override pyproject.toml, setup.cfg, or setup.py
requires_python_str: Optional[str] = os.environ.get(
"CIBW_PROJECT_REQUIRES_PYTHON"
Expand Down Expand Up @@ -270,13 +256,6 @@ def main() -> None:
# This needs to be passed on to the docker container in linux.py
os.environ["CIBUILDWHEEL"] = "1"

if args.archs is not None:
archs_config_str = args.archs
else:
archs_config_str = get_option_from_environment(
"CIBW_ARCHS", platform=platform, default="auto"
)

archs = Architecture.parse_config(archs_config_str, platform=platform)

identifiers = get_build_identifiers(platform, build_selector, archs)
Expand All @@ -286,7 +265,7 @@ def main() -> None:
print(identifier)
sys.exit(0)

manylinux_images: Optional[Dict[str, str]] = None
manylinux_images: Dict[str, str] = {}
if platform == "linux":
pinned_docker_images_file = resources_dir / "pinned_docker_images.cfg"
all_pinned_docker_images = ConfigParser()
Expand All @@ -297,22 +276,10 @@ def main() -> None:
# 'pypy_x86_64': {'manylinux2010': '...' }
# ... }

manylinux_images = {}

for build_platform in [
"x86_64",
"i686",
"pypy_x86_64",
"aarch64",
"ppc64le",
"s390x",
"pypy_aarch64",
"pypy_i686",
]:
for build_platform in MANYLINUX_ARCHS:
pinned_images = all_pinned_docker_images[build_platform]

config_name = f"CIBW_MANYLINUX_{build_platform.upper()}_IMAGE"
config_value = os.environ.get(config_name)
config_value = options(f"manylinux-{build_platform}-image")

if config_value is None:
# default to manylinux2010 if it's available, otherwise manylinux2014
Expand Down Expand Up @@ -340,7 +307,7 @@ def main() -> None:
repair_command=repair_command,
environment=environment,
dependency_constraints=dependency_constraints,
manylinux_images=manylinux_images,
manylinux_images=manylinux_images or None,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for later: some tests assume this is none, but it probably is simpler type-wise just to leave it an empty set. Potential cleanup unrelated to this PR, though.

)

# Python is buffering by default when running on the CI platforms, giving problems interleaving subprocess call output with unflushed calls to 'print'
Expand Down
Loading