1from abc import ABCMeta, abstractproperty 2 3import six 4 5from conans.errors import ConanException 6from conans.model.build_info import COMPONENT_SCOPE 7 8 9@six.add_metaclass(ABCMeta) 10class Generator(object): 11 name = None 12 13 def __init__(self, conanfile): 14 self.conanfile = conanfile 15 self.normalize = True 16 self._deps_build_info = conanfile.deps_cpp_info 17 self._deps_env_info = conanfile.deps_env_info 18 self._env_info = conanfile.env_info 19 self._deps_user_info = conanfile.deps_user_info 20 self._user_info_build = getattr(conanfile, 'user_info_build', None) 21 22 @classmethod 23 def _get_name(cls, obj): 24 return obj.get_name(cls.name) 25 26 @property 27 def deps_build_info(self): 28 return self._deps_build_info 29 30 @property 31 def deps_env_info(self): 32 return self._deps_env_info 33 34 @property 35 def deps_user_info(self): 36 return self._deps_user_info 37 38 @property 39 def env_info(self): 40 return self._env_info 41 42 @property 43 def settings(self): 44 return self.conanfile.settings 45 46 @abstractproperty 47 def content(self): 48 raise NotImplementedError() 49 50 @abstractproperty 51 def filename(self): 52 raise NotImplementedError() 53 54 def get_public_deps(self, cpp_info): 55 return cpp_info.public_deps 56 57 58class GeneratorComponentsMixin(object): 59 60 @classmethod 61 def sorted_components(self, cpp_info): 62 return cpp_info._get_sorted_components() 63 64 def _validate_components(self, cpp_info): 65 """ Check that all required components are provided by the dependencies """ 66 67 def _check_component_in_requirements(require): 68 if COMPONENT_SCOPE in require: 69 req_name, req_comp_name = require.split(COMPONENT_SCOPE) 70 if req_name == req_comp_name: 71 return 72 if req_comp_name not in self.deps_build_info[req_name].components: 73 raise ConanException("Component '%s' not found in '%s' package requirement" 74 % (require, req_name)) 75 76 for comp_name, comp in cpp_info.components.items(): 77 for cmp_require in comp.requires: 78 _check_component_in_requirements(cmp_require) 79 80 for pkg_require in cpp_info.requires: 81 _check_component_in_requirements(pkg_require) 82 83 def _get_require_name(self, pkg_name, req): 84 pkg, cmp = req.split(COMPONENT_SCOPE) if COMPONENT_SCOPE in req else (pkg_name, req) 85 pkg_build_info = self.deps_build_info[pkg] 86 pkg_name = self._get_name(pkg_build_info) 87 # fallback namespace to pkg_name if not defined 88 pkg_namespace = pkg_name 89 if cmp in pkg_build_info.components: 90 cmp_name = self._get_name(pkg_build_info.components[cmp]) 91 else: 92 cmp_name = pkg_name 93 return pkg_namespace, cmp_name 94 95 def _get_components(self, pkg_name, cpp_info): 96 ret = [] 97 for comp_name, comp in self.sorted_components(cpp_info).items(): 98 comp_genname = self._get_name(cpp_info.components[comp_name]) 99 comp_requires_gennames = [] 100 for require in comp.requires: 101 comp_requires_gennames.append(self._get_require_name(pkg_name, require)) 102 ret.append((comp_genname, comp, comp_requires_gennames)) 103 ret.reverse() 104 return ret 105 106 @classmethod 107 def get_public_deps(cls, cpp_info): 108 if cpp_info.requires: 109 deps = [it for it in cpp_info.requires if COMPONENT_SCOPE in it] 110 return [it.split(COMPONENT_SCOPE) for it in deps] 111 else: 112 return [(it, it) for it in cpp_info.public_deps] 113