diff --git a/conan.conf b/conan.conf deleted file mode 100644 index 0ab8d76..0000000 --- a/conan.conf +++ /dev/null @@ -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 diff --git a/extensions/deployers/virtual_python_env.py b/extensions/deployers/virtual_python_env.py new file mode 100644 index 0000000..ecc6d52 --- /dev/null +++ b/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") diff --git a/generators/GitHubActionsBuildEnv.py b/extensions/generators/GitHubActionsBuildEnv.py similarity index 100% rename from generators/GitHubActionsBuildEnv.py rename to extensions/generators/GitHubActionsBuildEnv.py diff --git a/generators/GitHubActionsRunEnv.py b/extensions/generators/GitHubActionsRunEnv.py similarity index 100% rename from generators/GitHubActionsRunEnv.py rename to extensions/generators/GitHubActionsRunEnv.py diff --git a/generators/PyCharmRunEnv.py b/extensions/generators/PyCharmRunEnv.py similarity index 100% rename from generators/PyCharmRunEnv.py rename to extensions/generators/PyCharmRunEnv.py diff --git a/generators/VirtualPythonEnv.py b/generators/VirtualPythonEnv.py deleted file mode 100644 index acd7e50..0000000 --- a/generators/VirtualPythonEnv.py +++ /dev/null @@ -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 - } diff --git a/global.conf b/global.conf index 33886ac..5cea560 100644 --- a/global.conf +++ b/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 %} \ No newline at end of file diff --git a/profiles/cura.jinja b/profiles/cura.jinja index 073d99d..0d7faa9 100644 --- a/profiles/cura.jinja +++ b/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] diff --git a/profiles/cura_build.jinja b/profiles/cura_build.jinja index c747fd0..de80517 100644 --- a/profiles/cura_build.jinja +++ b/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] diff --git a/remotes.json b/remotes.json new file mode 100644 index 0000000..8cd6759 --- /dev/null +++ b/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 + } + ] +} \ No newline at end of file diff --git a/remotes.txt b/remotes.txt deleted file mode 100644 index 69e3f5a..0000000 --- a/remotes.txt +++ /dev/null @@ -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