conans/model/conan_generator.py
from abc import ABCMeta, abstractproperty
import six
from conans.errors import ConanException
from conans.model.build_info import COMPONENT_SCOPE
@six.add_metaclass(ABCMeta)
class Generator(object):
name = None
def __init__(self, conanfile):
self.conanfile = conanfile
self.normalize = True
self._deps_build_info = conanfile.deps_cpp_info
self._deps_env_info = conanfile.deps_env_info
self._env_info = conanfile.env_info
self._deps_user_info = conanfile.deps_user_info
self._user_info_build = getattr(conanfile, 'user_info_build', None)
@classmethod
def _get_name(cls, obj):
return obj.get_name(cls.name)
@property
def deps_build_info(self):
return self._deps_build_info
@property
def deps_env_info(self):
return self._deps_env_info
@property
def deps_user_info(self):
return self._deps_user_info
@property
def env_info(self):
return self._env_info
@property
def settings(self):
return self.conanfile.settings
@abstractproperty
def content(self):
raise NotImplementedError()
@abstractproperty
def filename(self):
raise NotImplementedError()
def get_public_deps(self, cpp_info):
return cpp_info.public_deps
class GeneratorComponentsMixin(object):
@classmethod
def sorted_components(self, cpp_info):
return cpp_info._get_sorted_components()
def _validate_components(self, cpp_info):
""" Check that all required components are provided by the dependencies """
def _check_component_in_requirements(require):
if COMPONENT_SCOPE in require:
req_name, req_comp_name = require.split(COMPONENT_SCOPE)
if req_name == req_comp_name:
return
if req_comp_name not in self.deps_build_info[req_name].components:
raise ConanException("Component '%s' not found in '%s' package requirement"
% (require, req_name))
for comp_name, comp in cpp_info.components.items():
for cmp_require in comp.requires:
_check_component_in_requirements(cmp_require)
for pkg_require in cpp_info.requires:
_check_component_in_requirements(pkg_require)
def _get_require_name(self, pkg_name, req):
pkg, cmp = req.split(COMPONENT_SCOPE) if COMPONENT_SCOPE in req else (pkg_name, req)
pkg_build_info = self.deps_build_info[pkg]
pkg_name = self._get_name(pkg_build_info)
# fallback namespace to pkg_name if not defined
pkg_namespace = pkg_name
if cmp in pkg_build_info.components:
cmp_name = self._get_name(pkg_build_info.components[cmp])
else:
cmp_name = pkg_name
return pkg_namespace, cmp_name
def _get_components(self, pkg_name, cpp_info):
ret = []
for comp_name, comp in self.sorted_components(cpp_info).items():
comp_genname = self._get_name(cpp_info.components[comp_name])
comp_requires_gennames = []
for require in comp.requires:
comp_requires_gennames.append(self._get_require_name(pkg_name, require))
ret.append((comp_genname, comp, comp_requires_gennames))
ret.reverse()
return ret
@classmethod
def get_public_deps(cls, cpp_info):
if cpp_info.requires:
deps = [it for it in cpp_info.requires if COMPONENT_SCOPE in it]
return [it.split(COMPONENT_SCOPE) for it in deps]
else:
return [(it, it) for it in cpp_info.public_deps]