You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

105 lines
4.9 KiB

import os
import sys
from io import StringIO
from shutil import which
from pathlib import Path
from conan import ConanFile
from conan.errors import ConanException
from conan.tools.files import copy, save, load
from conan.tools.scm import Version
from conan.tools.env import VirtualRunEnv
def deploy(graph, output_folder, **kwargs):
conanfile: ConanFile = graph.root.conanfile
bin_venv_path = "Scripts" if conanfile.settings.os == "Windows" else "bin"
# Check if CPython is added as a dependency use the Conan recipe if available; if not use system interpreter
try:
cpython = conanfile.dependencies["cpython"]
py_interp = cpython.conf_info.get("user.cpython:python").replace("\\", "/")
except KeyError:
py_interp = sys.executable
run_env = VirtualRunEnv(conanfile)
env = run_env.environment()
sys_vars = env.vars(conanfile, scope="run")
with sys_vars.apply():
conanfile.run(f"""{py_interp} -m venv --copies {output_folder}""", env="conanrun", scope="run")
# Make sure there executable is named the same on all three OSes this allows it to be called with `python`
# simplifying GH Actions steps
if conanfile.settings.os != "Windows":
py_interp_venv = Path(output_folder, bin_venv_path, "python")
if not py_interp_venv.exists():
py_interp_venv.hardlink_to(
Path(output_folder, bin_venv_path, Path(sys.executable).stem + Path(sys.executable).suffix))
else:
py_interp_venv = Path(output_folder, bin_venv_path,
Path(sys.executable).stem + Path(sys.executable).suffix)
buffer = StringIO()
outer = '"' if conanfile.settings.os == "Windows" else "'"
inner = "'" if conanfile.settings.os == "Windows" else '"'
with sys_vars.apply():
conanfile.run(
f"""{py_interp_venv} -c {outer}import sysconfig; print(sysconfig.get_path({inner}purelib{inner})){outer}""",
env="conanrun",
stdout=buffer)
pythonpath = buffer.getvalue().splitlines()[-1]
env.define_path("VIRTUAL_ENV", output_folder)
env.prepend_path("PATH", os.path.join(output_folder, bin_venv_path))
env.prepend_path("LD_LIBRARY_PATH", os.path.join(output_folder, bin_venv_path))
env.prepend_path("DYLD_LIBRARY_PATH", os.path.join(output_folder, bin_venv_path))
env.prepend_path("PYTHONPATH", pythonpath)
env.unset("PYTHONHOME")
venv_vars = env.vars(conanfile, scope="run")
venv_vars.save_script("virtual_python_env")
# Install some base_packages
with venv_vars.apply():
conanfile.run(f"""{py_interp_venv} -m pip install wheel setuptools""", env="conanrun")
if conanfile.settings.os != "Windows":
content = f"source {os.path.join(output_folder, 'conan', 'virtual_python_env.sh')}\n" + load(conanfile,
os.path.join(
output_folder,
bin_venv_path,
"activate"))
save(conanfile, os.path.join(output_folder, bin_venv_path, "activate"), content)
pip_requirements = {}
if conanfile.conan_data is not None and "pip_requirements" in conanfile.conan_data:
for oses in ("any", str(conanfile.settings.os)):
for name, req in conanfile.conan_data["pip_requirements"][oses].items():
if name not in pip_requirements or Version(pip_requirements[name]["version"]) < Version(req["version"]):
pip_requirements[name] = req
for name, dep in reversed(conanfile.dependencies.host.items()):
if dep.conan_data is None:
continue
if "pip_requirements" in dep.conan_data:
for oses in ("any", str(conanfile.settings.os)):
for name, req in conanfile.conan_data["pip_requirements"][oses].items():
if name not in pip_requirements or Version(pip_requirements[name]["version"]) < Version(
req["version"]):
pip_requirements[name] = req
requirements_txt = ""
for name, req in pip_requirements.items():
if "url" in req:
requirements_txt += f"{req['url']}"
else:
requirements_txt += f"{name}=={req['version']}"
for hash_str in req['hashes']:
requirements_txt += f" --hash={hash_str}"
requirements_txt += "\n"
save(conanfile, os.path.join(output_folder, 'conan', 'requirements.txt'), requirements_txt)
with venv_vars.apply():
conanfile.run(f"{py_interp_venv} -m pip install -r {os.path.join(output_folder, 'conan', 'requirements.txt')}",
env="conanrun")