Browse Source

Getting the configuration ready for Conan v2

Contributes to CURA-11622
pull/12/head
Jelle Spijker 2 years ago
parent
commit
491dc7c006
No known key found for this signature in database
GPG Key ID: E9129B3096F4E72
  1. 24
      conan.conf
  2. 105
      extensions/deployers/virtual_python_env.py
  3. 0
      extensions/generators/GitHubActionsBuildEnv.py
  4. 0
      extensions/generators/GitHubActionsRunEnv.py
  5. 0
      extensions/generators/PyCharmRunEnv.py
  6. 174
      generators/VirtualPythonEnv.py
  7. 6
      global.conf
  8. 23
      profiles/cura.jinja
  9. 11
      profiles/cura_build.jinja
  10. 19
      remotes.json
  11. 2
      remotes.txt

24
conan.conf

@ -1,24 +0,0 @@
[log]
run_to_output = True # environment CONAN_LOG_RUN_TO_OUTPUT
run_to_file = False # environment CONAN_LOG_RUN_TO_FILE
level = warn # environment CONAN_LOGGING_LEVEL
print_run_commands = True # environment CONAN_PRINT_RUN_COMMANDS
[general]
default_profile = default
compression_level = 9 # environment CONAN_COMPRESSION_LEVEL
sysrequires_sudo = True # environment CONAN_SYSREQUIRES_SUDO
request_timeout = 60 # environment CONAN_REQUEST_TIMEOUT (seconds)
default_package_id_mode = full_package_mode # environment CONAN_DEFAULT_PACKAGE_ID_MODE
revisions_enabled = True
scm_to_conandata = True
use_always_short_paths = True
config_install_interval = 12h
[storage]
path = ./data
[proxies]
[hooks]
attribute_checker

105
extensions/deployers/virtual_python_env.py

@ -0,0 +1,105 @@
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")

0
generators/GitHubActionsBuildEnv.py → extensions/generators/GitHubActionsBuildEnv.py

0
generators/GitHubActionsRunEnv.py → extensions/generators/GitHubActionsRunEnv.py

0
generators/PyCharmRunEnv.py → extensions/generators/PyCharmRunEnv.py

174
generators/VirtualPythonEnv.py

@ -1,174 +0,0 @@
import sys
import os
from io import StringIO
from pathlib import Path
from jinja2 import Template
from conan import ConanFile
from conan.tools.env import VirtualRunEnv
from conans.model import Generator
from conans.errors import ConanException
class VirtualPythonEnv(Generator):
@property
def _script_ext(self):
if self.conanfile.settings.get_safe("os") == "Windows":
return ".ps1"
return ".sh"
@property
def _venv_path(self):
if self.settings.os == "Windows":
return "Scripts"
return "bin"
@property
def filename(self):
pass
@property
def content(self):
conanfile: ConanFile = self.conanfile
python_interpreter = Path(self.conanfile.deps_user_info["cpython"].python)
# When on Windows execute as Windows Path
if conanfile.settings.os == "Windows":
python_interpreter = Path(*[f'"{p}"' if " " in p else p for p in python_interpreter.parts])
# Create the virtual environment
print(f"Creating virtual environment in {conanfile.install_folder}")
print(f"Creating virtual environment in {conanfile.build_folder}")
if conanfile.in_local_cache:
venv_folder = conanfile.install_folder
else:
venv_folder = conanfile.build_folder if conanfile.build_folder else Path(os.getcwd(), "venv")
conanfile.output.info(f"Creating virtual environment in {venv_folder}")
conanfile.run(f"""{python_interpreter} -m venv {venv_folder}""", run_environment = True, env = "conanrun")
# 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":
python_venv_interpreter = Path(venv_folder, self._venv_path, "python")
if not python_venv_interpreter.exists():
python_venv_interpreter.hardlink_to(
Path(venv_folder, self._venv_path, Path(sys.executable).stem + Path(sys.executable).suffix))
else:
python_venv_interpreter = Path(venv_folder, self._venv_path, Path(sys.executable).stem + Path(sys.executable).suffix)
if not python_venv_interpreter.exists():
raise ConanException(f"Virtual environment Python interpreter not found at: {python_venv_interpreter}")
if conanfile.settings.os == "Windows":
python_venv_interpreter = Path(*[f'"{p}"' if " " in p else p for p in python_venv_interpreter.parts])
buffer = StringIO()
outer = '"' if conanfile.settings.os == "Windows" else "'"
inner = "'" if conanfile.settings.os == "Windows" else '"'
conanfile.run(f"{python_venv_interpreter} -c {outer}import sysconfig; print(sysconfig.get_path({inner}purelib{inner})){outer}",
env = "conanrun",
output = buffer)
pythonpath = buffer.getvalue().splitlines()[-1]
run_env = VirtualRunEnv(conanfile)
env = run_env.environment()
if hasattr(self.conanfile, f"_{self.conanfile.name}_run_env"):
project_run_env = getattr(self.conanfile, f"_{self.conanfile.name}_run_env")
if project_run_env:
env.compose_env(project_run_env) # TODO: Add logic for dependencies
env.define_path("VIRTUAL_ENV", venv_folder)
env.prepend_path("PATH", os.path.join(venv_folder, self._venv_path))
env.prepend_path("LD_LIBRARY_PATH", os.path.join(venv_folder, self._venv_path))
env.prepend_path("DYLD_LIBRARY_PATH", os.path.join(venv_folder, self._venv_path))
env.prepend_path("PYTHONPATH", pythonpath)
env.unset("PYTHONHOME")
# Install some base_packages
conanfile.run(f"""{python_venv_interpreter} -m pip install wheel setuptools""", run_environment = True, env = "conanrun")
# Install pip_requirements from dependencies
for dep_name in reversed(conanfile.deps_user_info):
dep_user_info = conanfile.deps_user_info[dep_name]
if len(dep_user_info.vars) == 0:
continue
pip_req_paths = [conanfile.deps_cpp_info[dep_name].res_paths[i] for i, req_path in
enumerate(conanfile.deps_cpp_info[dep_name].resdirs) if req_path.endswith("pip_requirements")]
if len(pip_req_paths) != 1:
continue
pip_req_base_path = Path(pip_req_paths[0])
if hasattr(dep_user_info, "pip_requirements"):
req_txt = pip_req_base_path.joinpath(dep_user_info.pip_requirements)
if req_txt.exists():
conanfile.run(f"{python_venv_interpreter} -m pip install -r {req_txt} --upgrade", run_environment = True,
env = "conanrun")
conanfile.output.success(f"Dependency {dep_name} specifies pip_requirements in user_info installed!")
else:
conanfile.output.warn(f"Dependency {dep_name} specifies pip_requirements in user_info but {req_txt} can't be found!")
if hasattr(dep_user_info, "pip_requirements_git"):
req_txt = pip_req_base_path.joinpath(dep_user_info.pip_requirements_git)
if req_txt.exists():
conanfile.run(f"{python_venv_interpreter} -m pip install -r {req_txt} --upgrade", run_environment = True,
env = "conanrun")
conanfile.output.success(f"Dependency {dep_name} specifies pip_requirements_git in user_info installed!")
else:
conanfile.output.warn(
f"Dependency {dep_name} specifies pip_requirements_git in user_info but {req_txt} can't be found!")
if hasattr(dep_user_info, "pip_requirements_build"):
req_txt = pip_req_base_path.joinpath(dep_user_info.pip_requirements_build)
if req_txt.exists():
conanfile.run(f"{python_venv_interpreter} -m pip install -r {req_txt} --upgrade", run_environment = True,
env = "conanrun")
conanfile.output.success(f"Dependency {dep_name} specifies pip_requirements_build in user_info installed!")
else:
conanfile.output.warn(
f"Dependency {dep_name} specifies pip_requirements_build in user_info but {req_txt} can't be found!")
if not conanfile.in_local_cache and hasattr(conanfile, "requirements_txts"):
# Install the Python requirements of the current conanfile requirements*.txt
pip_req_base_path = Path(conanfile.source_folder)
for req_path in sorted(conanfile.requirements_txts, reverse = True):
req_txt = pip_req_base_path.joinpath(req_path)
if req_txt.exists():
conanfile.run(f"{python_venv_interpreter} -m pip install -r {req_txt} --upgrade", run_environment = True,
env = "conanrun")
conanfile.output.success(f"Requirements file {req_txt} installed!")
else:
conanfile.output.warn(f"Requirements file {req_txt} can't be found!")
# Add all dlls/dylibs/so found in site-packages to the PATH, DYLD_LIBRARY_PATH and LD_LIBRARY_PATH
dll_paths = list({ dll.parent for dll in Path(pythonpath).glob("**/*.dll") })
for dll_path in dll_paths:
env.append_path("PATH", str(dll_path))
dylib_paths = list({ dylib.parent for dylib in Path(pythonpath).glob("**/*.dylib") })
for dylib_path in dylib_paths:
env.append_path("DYLD_LIBRARY_PATH", str(dylib_path))
so_paths = list({ so.parent for so in Path(pythonpath).glob("**/*.dylib") })
for so_path in so_paths:
env.append_path("LD_LIBRARY_PATH", str(so_path))
full_envvars = env.vars(conanfile, scope = "conanrun")
# Generate the Python Virtual Environment Script
full_envvars.save_sh(Path(venv_folder, self._venv_path, "activate"))
full_envvars.save_bat(Path(venv_folder, self._venv_path, "activate.bat"))
full_envvars.save_ps1(Path(venv_folder, self._venv_path, "Activate.ps1"))
# Generate the GitHub Action activation script
env_prefix = "Env:" if conanfile.settings.os == "Windows" else ""
activate_github_actions_buildenv = Template(r"""{% for var, value in envvars.items() %}echo "{{ var }}={{ value }}" >> ${{ env_prefix }}GITHUB_ENV
{% endfor %}""").render(envvars = full_envvars, env_prefix = env_prefix)
return {
str(Path(venv_folder, self._venv_path, f"activate_github_actions_env{self._script_ext}")): activate_github_actions_buildenv
}

6
global.conf

@ -1,11 +1,7 @@
core:default_profile = cura.jinja
core:default_build_profile = cura_build.jinja
tools.cmake.cmaketoolchain:generator = Ninja
tools.env.virtualenv:auto_use = True
tools.gnu:define_libcxx11_abi = True
tools.build:skip_test = False
# FIXME: Needs to be commented out for OpenSSL to work but if we wan't to create ps1 scripts it needs to be set to True
# Otherwise .bat files are created. Maybe we should define this on a recipe basis:
#
#{% if platform.system() == 'Windows' %}tools.env.virtualenv:powershell=True{% endif %}
{% if platform.system() == 'Windows' %}tools.env.virtualenv:powershell=True{% endif %}

23
profiles/cura.jinja

@ -1,24 +1,13 @@
include(default)
[build_requires]
[settings]
compiler.cppstd=17
curaengine:compiler.cppstd=20
curaengine*:compiler.cppstd=20
curaengine_plugin_infill_generate:compiler.cppstd=20
curaengine_plugin_gradual_flow:compiler.cppstd=20
curaengine_grpc_definitions:compiler.cppstd=20
scripta:compiler.cppstd=20
curaengine_plugin_infill_generate*:compiler.cppstd=20
curaengine_plugin_gradual_flow*:compiler.cppstd=20
curaengine_grpc_definitions*:compiler.cppstd=20
scripta*:compiler.cppstd=20
umspatial*:compiler.cppstd=20
dulcificum:compiler.cppstd=20
cura_settings:compiler.cppstd=20
dulcificum*:compiler.cppstd=20
cura_settings*:compiler.cppstd=20
{% if compiler == 'gcc' %}compiler.libcxx=libstdc++11
{% elif compiler == 'apple-clang' %}compiler.libcxx=libc++
{% elif compiler == 'Visual Studio' %}compiler.toolset=v143
{% endif %}
[options]
[env]
cpython*:CONAN_DISABLE_STRICT_MODE=1
[conf]

11
profiles/cura_build.jinja

@ -1,15 +1,4 @@
include(default)
[build_requires]
[settings]
compiler.cppstd=17
{% if compiler == 'gcc' %}compiler.libcxx=libstdc++11
{% elif compiler == 'apple-clang' %}compiler.libcxx=libc++
{% elif compiler == 'Visual Studio' %}compiler.toolset=v143
{% endif %}
[options]
[env]
[conf]

19
remotes.json

@ -0,0 +1,19 @@
{
"remotes": [
{
"name": "conancenter",
"url": "https://center.conan.io",
"verify_ssl": true
},
{
"name": "cura",
"url": "https://cura.jfrog.io/artifactory/api/conan/cura-conan-dev",
"verify_ssl": true
},
{
"name": "cura-private",
"url": "https://cura.jfrog.io/artifactory/api/conan/cura-private-conan-dev",
"verify_ssl": true
}
]
}

2
remotes.txt

@ -1,2 +0,0 @@
cura https://cura.jfrog.io/artifactory/api/conan/cura-conan-dev True
cura-private https://cura.jfrog.io/artifactory/api/conan/cura-private-conan-dev True
Loading…
Cancel
Save