Switch to potential new distutils environment variable

This commit is contained in:
Steve Dower
2022-09-01 22:13:08 +01:00
parent 44ebbc4460
commit 1d7054c022
+86 -141
View File
@@ -133,50 +133,10 @@ def setup_setuptools_cross_compile(
python_configuration: PythonConfiguration, python_configuration: PythonConfiguration,
python_libs_base: Path, python_libs_base: Path,
env: dict[str, str], env: dict[str, str],
cleanup_command_list: list[Callable[[], Any]],
) -> None: ) -> None:
# We write to distutils_cfg for distutils-based builds to override some distutils_cfg = python_libs_base / "extra-setup.cfg"
# settings. Ideally, we'd pass them on the command line, but since we don't env["DISTUTILS_EXTRA_CONFIG"] = str(distutils_cfg)
# know that setuptools is going to be used, we can't do it. log.notice(f"Setting DISTUTILS_EXTRA_CONFIG={distutils_cfg} for cross-compilation")
userprofile = os.getenv("USERPROFILE")
if not userprofile:
log.warning(
"Unable to configure setuptools for cross-compiling because USERPROFILE was not found"
)
return
distutils_cfg = Path(userprofile) / "pydistutils.cfg"
if distutils_cfg.is_file():
# More than 1000 backup files is likely a different issue, so don't
# bother going further than that.
for counter in range(1000):
distutils_bak = distutils_cfg.with_suffix(f".{counter}.bak")
if not distutils_bak.exists():
break
else:
log.warning(
f"Unable to configure setuptools for cross-compiling because existing {distutils_cfg} file cannot be backed up: Too many existing backup files were found"
)
return
# Move the existing file and restore it when we exit
log.notice(
f"Preserving {distutils_cfg} as {distutils_bak.name}. It will be restored afterwards."
)
try:
distutils_cfg.replace(distutils_bak)
except OSError as exc:
log.warning(
f"Unable to configure setuptools for cross-compiling because existing {distutils_cfg} file cannot be backed up. Error was {exc}"
)
return
cleanup_command_list.append(lambda: distutils_bak.replace(distutils_cfg))
elif distutils_cfg.is_dir():
log.warning(
f"Unable to configure setuptools for cross-compiling because {distutils_cfg} is a directory"
)
return
else:
cleanup_command_list.append(lambda: distutils_cfg.unlink())
# Ensure our additional import libraries are made available, and explicitly # Ensure our additional import libraries are made available, and explicitly
# set the platform name # set the platform name
@@ -186,8 +146,6 @@ def setup_setuptools_cross_compile(
distutils_cfg.write_text( distutils_cfg.write_text(
textwrap.dedent( textwrap.dedent(
f"""\ f"""\
# I am a temporary configuration file generated by cibuildwheel.
# Please remove me or I will likely break your other builds.
[build] [build]
plat_name={plat_name} plat_name={plat_name}
[build_ext] [build_ext]
@@ -221,7 +179,6 @@ def setup_rust_cross_compile(
python_configuration: PythonConfiguration, python_configuration: PythonConfiguration,
python_libs_base: Path, python_libs_base: Path,
env: dict[str, str], env: dict[str, str],
cleanup_command_list: list[Callable[[], Any]],
) -> None: ) -> None:
# Assume that MSVC will be used, because we already know that we are # Assume that MSVC will be used, because we already know that we are
# cross-compiling. MinGW users can set CARGO_BUILD_TARGET themselves # cross-compiling. MinGW users can set CARGO_BUILD_TARGET themselves
@@ -252,7 +209,6 @@ def setup_python(
dependency_constraint_flags: Sequence[PathOrStr], dependency_constraint_flags: Sequence[PathOrStr],
environment: ParsedEnvironment, environment: ParsedEnvironment,
build_frontend: BuildFrontend, build_frontend: BuildFrontend,
cleanup_command_list: list[Callable[[], Any]],
) -> dict[str, str]: ) -> dict[str, str]:
tmp.mkdir() tmp.mkdir()
implementation_id = python_configuration.identifier.split("-")[0] implementation_id = python_configuration.identifier.split("-")[0]
@@ -374,10 +330,8 @@ def setup_python(
if python_libs_base: if python_libs_base:
# Set up the environment for various backends to enable cross-compilation # Set up the environment for various backends to enable cross-compilation
setup_setuptools_cross_compile( setup_setuptools_cross_compile(python_configuration, python_libs_base, env)
python_configuration, python_libs_base, env, cleanup_command_list setup_rust_cross_compile(python_configuration, python_libs_base, env)
)
setup_rust_cross_compile(python_configuration, python_libs_base, env, cleanup_command_list)
return env return env
@@ -420,9 +374,6 @@ def build(options: Options, tmp_path: Path) -> None:
build_options.dependency_constraints.get_for_python_version(config.version), build_options.dependency_constraints.get_for_python_version(config.version),
] ]
# list of callables to do any urgent cleanup, for example,
# config files that may bleed into other builds
cleanup_command_list: list[Callable[[], Any]] = []
# install Python # install Python
env = setup_python( env = setup_python(
identifier_tmp_dir / "build", identifier_tmp_dir / "build",
@@ -430,108 +381,102 @@ def build(options: Options, tmp_path: Path) -> None:
dependency_constraint_flags, dependency_constraint_flags,
build_options.environment, build_options.environment,
build_options.build_frontend, build_options.build_frontend,
cleanup_command_list,
) )
try: compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier) if compatible_wheel:
if compatible_wheel: log.step_end()
log.step_end() print(
print( f"\nFound previously built wheel {compatible_wheel.name}, that's compatible with {config.identifier}. Skipping build step..."
f"\nFound previously built wheel {compatible_wheel.name}, that's compatible with {config.identifier}. Skipping build step..." )
repaired_wheel = compatible_wheel
else:
# run the before_build command
if build_options.before_build:
log.step("Running before_build...")
before_build_prepared = prepare_command(
build_options.before_build,
project=".",
package=options.globals.package_dir,
) )
repaired_wheel = compatible_wheel shell(before_build_prepared, env=env)
else:
# run the before_build command log.step("Building wheel...")
if build_options.before_build: built_wheel_dir.mkdir()
log.step("Running before_build...")
before_build_prepared = prepare_command( verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
build_options.before_build,
project=".", if build_options.build_frontend == "pip":
package=options.globals.package_dir, # Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/pypa/cibuildwheel/pull/369
call(
"python",
"-m",
"pip",
"wheel",
options.globals.package_dir.resolve(),
f"--wheel-dir={built_wheel_dir}",
"--no-deps",
*get_build_verbosity_extra_flags(build_options.build_verbosity),
env=env,
)
elif build_options.build_frontend == "build":
config_setting = " ".join(verbosity_flags)
build_env = env.copy()
if build_options.dependency_constraints:
constraints_path = (
build_options.dependency_constraints.get_for_python_version(
config.version
)
) )
shell(before_build_prepared, env=env) # Bug in pip <= 21.1.3 - we can't have a space in the
# constraints file, and pip doesn't support drive letters
# in uhi. After probably pip 21.2, we can use uri. For
# now, use a temporary file.
if " " in str(constraints_path):
assert " " not in str(identifier_tmp_dir)
tmp_file = identifier_tmp_dir / "constraints.txt"
tmp_file.write_bytes(constraints_path.read_bytes())
constraints_path = tmp_file
log.step("Building wheel...") build_env["PIP_CONSTRAINT"] = str(constraints_path)
built_wheel_dir.mkdir() build_env["VIRTUALENV_PIP"] = get_pip_version(env)
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
if build_options.build_frontend == "pip":
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/pypa/cibuildwheel/pull/369
call( call(
"python", "python",
"-m", "-m",
"pip", "build",
"wheel", build_options.package_dir,
options.globals.package_dir.resolve(), "--wheel",
f"--wheel-dir={built_wheel_dir}", f"--outdir={built_wheel_dir}",
"--no-deps", f"--config-setting={config_setting}",
*get_build_verbosity_extra_flags(build_options.build_verbosity), env=build_env,
env=env,
) )
elif build_options.build_frontend == "build": else:
config_setting = " ".join(verbosity_flags) assert_never(build_options.build_frontend)
build_env = env.copy()
if build_options.dependency_constraints:
constraints_path = (
build_options.dependency_constraints.get_for_python_version(
config.version
)
)
# Bug in pip <= 21.1.3 - we can't have a space in the
# constraints file, and pip doesn't support drive letters
# in uhi. After probably pip 21.2, we can use uri. For
# now, use a temporary file.
if " " in str(constraints_path):
assert " " not in str(identifier_tmp_dir)
tmp_file = identifier_tmp_dir / "constraints.txt"
tmp_file.write_bytes(constraints_path.read_bytes())
constraints_path = tmp_file
build_env["PIP_CONSTRAINT"] = str(constraints_path) built_wheel = next(built_wheel_dir.glob("*.whl"))
build_env["VIRTUALENV_PIP"] = get_pip_version(env)
call(
"python",
"-m",
"build",
build_options.package_dir,
"--wheel",
f"--outdir={built_wheel_dir}",
f"--config-setting={config_setting}",
env=build_env,
)
else:
assert_never(build_options.build_frontend)
built_wheel = next(built_wheel_dir.glob("*.whl")) # repair the wheel
repaired_wheel_dir.mkdir()
# repair the wheel if built_wheel.name.endswith("none-any.whl"):
repaired_wheel_dir.mkdir() raise NonPlatformWheelError()
if built_wheel.name.endswith("none-any.whl"): if build_options.repair_command:
raise NonPlatformWheelError() log.step("Repairing wheel...")
repair_command_prepared = prepare_command(
build_options.repair_command,
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
)
shell(repair_command_prepared, env=env)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
if build_options.repair_command: repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
log.step("Repairing wheel...")
repair_command_prepared = prepare_command(
build_options.repair_command,
wheel=built_wheel,
dest_dir=repaired_wheel_dir,
)
shell(repair_command_prepared, env=env)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
repaired_wheel = next(repaired_wheel_dir.glob("*.whl")) if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
raise AlreadyBuiltWheelError(repaired_wheel.name)
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
raise AlreadyBuiltWheelError(repaired_wheel.name)
finally:
while cleanup_command_list:
cleanup_command_list.pop(0)()
if build_options.test_command and options.globals.test_selector(config.identifier): if build_options.test_command and options.globals.test_selector(config.identifier):
if config.arch == "ARM64" != platform_module.machine(): if config.arch == "ARM64" != platform_module.machine():