From f2fbfb43b85d34fd34db661f67290e83cac30528 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Mon, 12 Feb 2024 11:31:35 +0100 Subject: [PATCH] Use Conan v2 Contributes to CURA-11079 --- .github/workflows/conan-package.yml | 42 ++++--------- recipes/clipper/all/conanfile.py | 5 +- recipes/pyprojecttoolchain/all/conanfile.py | 40 +++++++----- recipes/sipbuildtool/all/conanfile.py | 14 +++-- recipes/translationextractor/all/conanfile.py | 62 ++++++++++++------- 5 files changed, 85 insertions(+), 78 deletions(-) diff --git a/.github/workflows/conan-package.yml b/.github/workflows/conan-package.yml index 3318641..328dba2 100644 --- a/.github/workflows/conan-package.yml +++ b/.github/workflows/conan-package.yml @@ -7,6 +7,8 @@ on: branches: - main - 'CURA-*' + - 'PP-*' + - 'NP-*' permissions: contents: read @@ -30,9 +32,10 @@ jobs: with: PATTERNS: | recipes/**/*.* - + +# FIXME: use main once merged - name: Sync pip requirements - run: wget https://raw.githubusercontent.com/Ultimaker/cura-workflows/main/.github/workflows/requirements-runner.txt -O .github/workflows/requirements-runner.txt + run: wget https://raw.githubusercontent.com/Ultimaker/cura-workflows/CURA-11622_conan_v2/.github/workflows/requirements-runner.txt -O .github/workflows/requirements-runner.txt - name: Setup Python and pip uses: actions/setup-python@v4 @@ -44,38 +47,19 @@ jobs: - name: Install Python requirements and Create default Conan profile run: pip install -r .github/workflows/requirements-runner.txt - - name: Setup pipeline caches - run: | - mkdir -p /home/runner/.conan/downloads - mkdir -p /home/runner/.conan/data - - name: Create default Conan profile - run: conan profile new default --detect + run: conan profile detect -f +# FIXME: use runner.os/runner.arch after merge: conan config install https://github.com/Ultimaker/conan-config.git -a "-b runner/runner.os/runner.arch" - name: Get Conan configuration run: | - conan config install https://github.com/Ultimaker/conan-config.git - conan config install https://github.com/Ultimaker/conan-config.git -a "-b runner/${{ runner.os }}/${{ runner.arch }}" - - - name: Cache Conan packages - uses: actions/cache@v3 - with: - path: /home/runner/.conan/data - key: ${{ runner.os }}-conan-data-${{ github.run_id }} - restore-keys: | - ${{ runner.os }}-conan-data- - - - name: Cache Conan downloads - uses: actions/cache@v3 - with: - path: /home/runner/.conan/downloads - key: ${{ runner.os }}-conan-downloads-${{ github.run_id }} - restore-keys: | - ${{ runner.os }}-conan-downloads- + conan config install https://github.com/Ultimaker/conan-config.git -a "-b CURA-11622_conan_v2" + conan remote login -p ${{ secrets.CONAN_PASS }} cura-conan-v2 ${{ secrets.CONAN_USER }} + #conan remote disable cura-private - # TODO: Change to main once merged +# TODO: Change to main once merged - name: Export changed recipes run: | mkdir runner_scripts - wget https://raw.githubusercontent.com/Ultimaker/cura-workflows/main/runner_scripts/upload_conan_recipes.py -O runner_scripts/upload_conan_recipes.py - python runner_scripts/upload_conan_recipes.py --user ultimaker --branch ${{ github.ref_name }} --remote cura ${{ env.GIT_DIFF_FILTERED }} + wget https://raw.githubusercontent.com/Ultimaker/cura-workflows/CURA-11622_conan_v2/runner_scripts/upload_conan_recipes.py -O runner_scripts/upload_conan_recipes.py + python runner_scripts/upload_conan_recipes.py --user ultimaker --branch ${{ github.ref_name }} --remote cura-conan-v2 ${{ env.GIT_DIFF_FILTERED }} diff --git a/recipes/clipper/all/conanfile.py b/recipes/clipper/all/conanfile.py index 7a708b5..2da22e4 100644 --- a/recipes/clipper/all/conanfile.py +++ b/recipes/clipper/all/conanfile.py @@ -1,11 +1,10 @@ -from io import StringIO +import os +from shutil import which from conan import ConanFile from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, rmdir from conan.errors import ConanInvalidConfiguration -from conans.tools import which -import os required_conan_version = ">=1.54.0" diff --git a/recipes/pyprojecttoolchain/all/conanfile.py b/recipes/pyprojecttoolchain/all/conanfile.py index b7b77c4..2dfc4cf 100644 --- a/recipes/pyprojecttoolchain/all/conanfile.py +++ b/recipes/pyprojecttoolchain/all/conanfile.py @@ -10,8 +10,8 @@ from conan.tools.gnu.autotoolstoolchain import AutotoolsToolchain from conan.tools.files import save from conan.errors import ConanInvalidConfiguration -from conan.tools._check_build_profile import check_using_build_profile -from conans.tools import Version +from conan.tools.scm import Version +from conan.tools import CppInfo class BuildSystemBlock(Block): @@ -55,8 +55,8 @@ def context(self): mod_version = Version(self._conanfile.version) pypi_version = f"{mod_version.major}.{mod_version.minor}.{mod_version.patch}" - if mod_version.prerelease != "": - split_prerelease = mod_version.prerelease.split(".") + if mod_version.pre != "": + split_prerelease = str(mod_version.pre).split(".") if len(split_prerelease) > 1: pypi_version += f"{split_prerelease[0][0]}{split_prerelease[1]}" else: @@ -89,10 +89,11 @@ def context(self): if py_lib_dir is None: try: - py_lib_dir = Path(self._conanfile.deps_cpp_info['cpython'].rootpath, self._conanfile.deps_cpp_info['cpython'].components["python"].bindirs[0], "libs").as_posix() - py_lib = self._conanfile.deps_cpp_info['cpython'].libs[0] + cpython_cpp = self._conanfile.dependencies["cpython"].cpp_info + py_lib_dir = Path(cpython_cpp.components["python"].libdirs[0]).as_posix() + py_lib = cpython_cpp.components["python"].libs[0] except: - self._conanfile.output.warn( + self._conanfile.output.warning( "No include directory set for Python.h, either add the options: 'py_include' of add cpython as a Conan dependency!") else: py_lib_dir = Path(py_lib_dir).as_posix() @@ -128,7 +129,7 @@ def context(self): try: python_version = self._conanfile.dependencies["cpython"].ref.version except: - self._conanfile.output.warn( + self._conanfile.output.warning( "No minimum required Python version specified, either add the options: 'py_version' of add cpython as a Conan dependency!") if python_version is not None: @@ -137,12 +138,11 @@ def context(self): if py_include_dir is None: try: header_path = "" if self._conanfile.settings.os == "Windows" else f"python{py_version.major}.{py_version.minor}" - py_include_dir = Path(self._conanfile.deps_cpp_info['cpython'].rootpath, - self._conanfile.deps_cpp_info['cpython'].components["python"].includedirs[0], - header_path).as_posix() + cpython_cpp = self._conanfile.dependencies["cpython"].cpp_info + py_include_dir = Path(cpython_cpp.components["python"].includedirs[0], header_path).as_posix() py_include_dir = f"py-include-dir = \"{py_include_dir}\"" except: - self._conanfile.output.warn( + self._conanfile.output.warning( "No include directory set for Python.h, either add the options: 'py_include' of add cpython as a Conan dependency!") else: py_include_dir = f"py-include-dir = \"{Path(py_include_dir).as_posix()}\"" @@ -210,13 +210,19 @@ class ToolSipBindingsBlock(Block): def context(self): settings = self._conanfile.settings - deps_cpp_info = self._conanfile.deps_cpp_info + aggregated_cpp_info = CppInfo(self._conanfile) + deps = self._conanfile.dependencies.host.topological_sort + deps = [dep for dep in reversed(deps.values())] + for dep in deps: + dep_cppinfo = dep.cpp_info.aggregated_components() + aggregated_cpp_info.merge(dep_cppinfo) + build_type = settings.get_safe("build_type", "Release") shared = settings.get_safe("shared", True) - libs = deps_cpp_info.libs - libdirs = [Path(d).as_posix() for d in deps_cpp_info.libdirs] - includedirs = [Path(d).as_posix() for d in deps_cpp_info.includedirs] + libs = aggregated_cpp_info.libs + libdirs = [Path(d).as_posix() for d in aggregated_cpp_info.libdirs] + includedirs = [Path(d).as_posix() for d in aggregated_cpp_info.includedirs] if self._conanfile.cpp.source.includedirs: includedirs.extend(self._conanfile.cpp.source.includedirs) @@ -243,7 +249,6 @@ class PyProjectToolchain(AutotoolsToolchain): def __init__(self, conanfile: ConanFile, namespace = None): super().__init__(conanfile, namespace) - check_using_build_profile(self._conanfile) blocks = [ ("build_system", BuildSystemBlock), @@ -283,3 +288,4 @@ def generate(self, env = None, scope = "build"): class PyProjectToolchainPkg(ConanFile): name = "pyprojecttoolchain" + package_type = "build-scripts" diff --git a/recipes/sipbuildtool/all/conanfile.py b/recipes/sipbuildtool/all/conanfile.py index ed0e76d..7d04df1 100644 --- a/recipes/sipbuildtool/all/conanfile.py +++ b/recipes/sipbuildtool/all/conanfile.py @@ -1,7 +1,8 @@ import os from conan import ConanFile -from conans import tools +from conan.tools.files import chdir, copy + from conans.client.subsystems import subsystem_path, deduce_subsystem @@ -16,29 +17,32 @@ class SipBuildTool(object): sip.configure() sip.generate("projectName") """ + def __init__(self, conanfile: ConanFile): self._conanfile = conanfile self._sip_install_executable = "sip-build" - def configure(self, sip_install_executable = None): + def configure(self, sip_install_executable=None): if sip_install_executable: self._sip_install_executable = sip_install_executable def build(self): - with tools.chdir(self._conanfile.source_folder): + with chdir(self, self._conanfile.source_folder): sip_cmd = self._sip_install_executable - subsystem = deduce_subsystem(self._conanfile, scope = "build") + subsystem = deduce_subsystem(self._conanfile, scope="build") sip_cmd = subsystem_path(subsystem, sip_cmd) cmd = '"{}"'.format(sip_cmd) self._conanfile.output.info(f"Calling:\n > {cmd}") self._conanfile.run(cmd) + class Pkg(ConanFile): name = "sipbuildtool" + package_type = "build-scripts" exports_sources = "SIPMacros.cmake" def package(self): - self.copy("SIPMacros.cmake", "cmake") + copy(self, pattern="*.cmake", src=self.export_sources_folder, dst=os.path.join(self.package_folder, "cmake")) def package_info(self): self.cpp_info.set_property("name", "sip") diff --git a/recipes/translationextractor/all/conanfile.py b/recipes/translationextractor/all/conanfile.py index bcdafb8..74d8922 100644 --- a/recipes/translationextractor/all/conanfile.py +++ b/recipes/translationextractor/all/conanfile.py @@ -19,7 +19,8 @@ def __init__(self, conanfile: ConanFile, gettext_bindir): self._conanfile = conanfile self._gettext_bindir = gettext_bindir self._translations_root_path = self._conanfile.source_path.joinpath("resources", "i18n") - self._all_strings_pot_path = self._translations_root_path.joinpath(self._conanfile.name + ".pot") # pot file containing all strings untranslated + self._all_strings_pot_path = self._translations_root_path.joinpath( + self._conanfile.name + ".pot") # pot file containing all strings untranslated self._pot_content = {} self._pot_are_updated = False @@ -31,14 +32,17 @@ def _update_po_files_all_languages(self) -> None: self._conanfile.output.info(f"Updating {po_file}") if lang_folder.is_dir() and not po_file.exists(): po_file.touch() - self._conanfile.run(f"{self._gettext_bindir}/msginit --no-translator -i {pot_file} -o {po_file} --locale=en") - self._conanfile.run(f"{self._gettext_bindir}/msgmerge --add-location=never --no-wrap --no-fuzzy-matching --sort-output -o {po_file} {po_file} {pot_file}", env = "conanbuild", run_environment = True) + self._conanfile.run( + f"{self._gettext_bindir}/msginit --no-translator -i {pot_file} -o {po_file} --locale=en") + self._conanfile.run( + f"{self._gettext_bindir}/msgmerge --add-location=never --no-wrap --no-fuzzy-matching --sort-output -o {po_file} {po_file} {pot_file}", + env="conanbuild") def _remove_pot_header(self, content: str) -> str: - return "".join(content.splitlines(keepends = True)[20:]) + return "".join(content.splitlines(keepends=True)[20:]) def _remove_comments(self, content: str) -> str: - return "".join([line for line in content.splitlines(keepends = True) if not line.startswith("#")]) + return "".join([line for line in content.splitlines(keepends=True) if not line.startswith("#")]) def _load_pot_content(self) -> None: for pot_file in Path(self._translations_root_path).rglob("*.pot"): @@ -48,7 +52,8 @@ def _load_pot_content(self) -> None: def _is_pot_content_changed(self, pot_file: str) -> bool: if pot_file not in self._pot_content: return False - return self._remove_comments(self._remove_pot_header(self._pot_content[pot_file])) != self._remove_comments(self._remove_pot_header(load(self._conanfile, pot_file))) + return self._remove_comments(self._remove_pot_header(self._pot_content[pot_file])) != self._remove_comments( + self._remove_pot_header(load(self._conanfile, pot_file))) def _only_update_pot_files_when_changed(self) -> None: """restore the previous content of the pot files if the content hasn't changed""" @@ -78,7 +83,7 @@ def _extract_python(self) -> None: continue self._conanfile.run( f"{self._gettext_bindir}/xgettext --from-code=UTF-8 --join-existing --add-location=never --sort-output --language=python --no-wrap -ki18n:1 -ki18nc:1c,2 -ki18np:1,2 -ki18ncp:1c,2,3 -o {self._all_strings_pot_path} {path}", - env = "conanbuild", run_environment = True) + env="conanbuild") def _extract_qml(self) -> None: """ Extract all i18n strings from qml files inside the root path """ @@ -87,7 +92,7 @@ def _extract_qml(self) -> None: continue self._conanfile.run( f"{self._gettext_bindir}/xgettext --from-code=UTF-8 --join-existing --add-location=never --sort-output --language=javascript --no-wrap -ki18n:1 -ki18nc:1c,2 -ki18np:1,2 -ki18ncp:1c,2,3 -o {self._all_strings_pot_path} {path}", - env = "conanbuild", run_environment = True) + env="conanbuild") def _extract_plugin(self) -> None: """ Extract the name and description from all plugins """ @@ -96,28 +101,31 @@ def _extract_plugin(self) -> None: translation_entries = "" # Extract translations from plugin.json - plugin_dict = json.loads(load(self._conanfile, path), object_pairs_hook = collections.OrderedDict) - if "name" not in plugin_dict or ("api" not in plugin_dict and "supported_sdk_versions" not in plugin_dict) or "version" not in plugin_dict: + plugin_dict = json.loads(load(self._conanfile, path), object_pairs_hook=collections.OrderedDict) + if "name" not in plugin_dict or ( + "api" not in plugin_dict and "supported_sdk_versions" not in plugin_dict) or "version" not in plugin_dict: self._conanfile.output.warn(f"The plugin.json is invalid, ignoring it: {path}") else: if "description" in plugin_dict: - translation_entries += self._create_translation_entry(path, "description", plugin_dict["description"]) + translation_entries += self._create_translation_entry(path, "description", + plugin_dict["description"]) if "name" in plugin_dict: translation_entries += self._create_translation_entry(path, "name", plugin_dict["name"]) # Write plugin name & description to output pot file if translation_entries: - save(self._conanfile, self._all_strings_pot_path, translation_entries, append = True) + save(self._conanfile, self._all_strings_pot_path, translation_entries, append=True) def _extract_settings(self) -> None: """ Extract strings from settings json files to pot file with a matching name """ - setting_json_paths = [path for path in self._conanfile.source_path.rglob("*.def.json") if "test" not in str(path)] + setting_json_paths = [path for path in self._conanfile.source_path.rglob("*.def.json") if + "test" not in str(path)] for path in setting_json_paths: self._write_setting_text(path, self._translations_root_path) def _write_setting_text(self, json_path: Path, destination_path: Path) -> bool: """ Writes settings text from json file to pot file. Returns true if a file was written. """ - setting_dict = json.loads(load(self._conanfile, json_path), object_pairs_hook = collections.OrderedDict) + setting_dict = json.loads(load(self._conanfile, json_path), object_pairs_hook=collections.OrderedDict) if "inherits" not in setting_dict: if "settings" in setting_dict: @@ -138,24 +146,31 @@ def _process_settings(self, file, settings) -> str: if "label" in value: translation_entries += self._create_setting_translation_entry(file, name, "label", value["label"]) if "description" in value: - translation_entries += self._create_setting_translation_entry(file, name, "description", value["description"]) + translation_entries += self._create_setting_translation_entry(file, name, "description", + value["description"]) if "warning_description" in value: - translation_entries += self._create_setting_translation_entry(file, name, "warning_description", value["warning_description"]) + translation_entries += self._create_setting_translation_entry(file, name, "warning_description", + value["warning_description"]) if "error_description" in value: - translation_entries += self._create_setting_translation_entry(file, name, "error_description", value["error_description"]) + translation_entries += self._create_setting_translation_entry(file, name, "error_description", + value["error_description"]) if "options" in value: for item, description in value["options"].items(): - translation_entries += self._create_setting_translation_entry(file, name, "option {0}".format(item), description) + translation_entries += self._create_setting_translation_entry(file, name, "option {0}".format(item), + description) if "children" in value: translation_entries += self._process_settings(file, value["children"]) return translation_entries def _create_setting_translation_entry(self, filename: str, setting: str, field: str, value: str) -> str: - return "msgctxt \"{0} {1}\"\nmsgid \"{2}\"\nmsgstr \"\"\n\n".format(setting, field, value.replace("\n", "\\n").replace("\"", "\\\"")) + return "msgctxt \"{0} {1}\"\nmsgid \"{2}\"\nmsgstr \"\"\n\n".format(setting, field, + value.replace("\n", "\\n").replace("\"", + "\\\"")) def _create_translation_entry(self, filename: str, field: str, value: str) -> str: - return "msgctxt \"{0}\"\nmsgid \"{1}\"\nmsgstr \"\"\n\n".format(field, value.replace("\n", "\\n").replace("\"", "\\\"")) + return "msgctxt \"{0}\"\nmsgid \"{1}\"\nmsgstr \"\"\n\n".format(field, value.replace("\n", "\\n").replace("\"", + "\\\"")) def _create_pot_header(self) -> str: """ Creates a pot file header """ @@ -187,7 +202,9 @@ def _sanitize_pot_files(self) -> None: self._conanfile.output.warn(f"Removing empty pot file: {path}") rm(self._conanfile, path.name, path.parent) else: - save(self._conanfile, path, content.replace(f"#: {self._conanfile.source_path}/", "#: ").replace("charset=CHARSET", "charset=UTF-8")) + save(self._conanfile, path, + content.replace(f"#: {self._conanfile.source_path}/", "#: ").replace("charset=CHARSET", + "charset=UTF-8")) def generate(self): self._load_pot_content() @@ -202,8 +219,5 @@ def generate(self): class Pkg(ConanFile): name = "translationextractor" - def package(self): - self.copy("*", ".") - def package_info(self): self.cpp_info.set_property("name", "translationextractor")