Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New cppinfo and CMakeDeps as example of usage #8766

Merged
merged 87 commits into from
Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
c2c7644
wip
czoido Mar 26, 2021
76c0a2f
wip
czoido Mar 26, 2021
12bd1d4
wip
czoido Mar 26, 2021
5f6332d
wip
czoido Mar 26, 2021
f0dadfd
wip
czoido Mar 27, 2021
aaa11da
wip
czoido Mar 27, 2021
7825939
wip
czoido Mar 27, 2021
c0f6432
fix
czoido Mar 29, 2021
3f93a30
wip
czoido Mar 29, 2021
e8f3c6f
wip
czoido Mar 29, 2021
6183b0a
wip
czoido Mar 29, 2021
216d829
wip
czoido Mar 29, 2021
40b33f1
remove unused
czoido Mar 29, 2021
9838b46
wip
czoido Mar 29, 2021
9d820a8
wip
czoido Mar 29, 2021
dcac203
wip
czoido Mar 29, 2021
e7eee31
wip
czoido Mar 29, 2021
77dce8f
wip
czoido Mar 29, 2021
4c6c42b
minor changes
czoido Mar 29, 2021
39a31db
wip
czoido Mar 29, 2021
3bb2de4
fix local flow
czoido Mar 30, 2021
919b5d2
wip
czoido Mar 30, 2021
90e6299
simplify code
czoido Mar 31, 2021
785cdbe
change update function name
czoido Mar 31, 2021
ec0475f
generalize name
czoido Mar 31, 2021
234add7
start build modules support
czoido Mar 31, 2021
54f497d
wip
czoido Mar 31, 2021
edc7fc1
wip
czoido Apr 1, 2021
ade9123
update test
czoido Apr 1, 2021
3d51f94
old behaviour
czoido Apr 1, 2021
9a22ca5
wip
czoido Apr 1, 2021
5b04a78
wip
czoido Apr 2, 2021
82188cb
add custom content to pkg-config generator
czoido Apr 3, 2021
dcf3de9
add tests with components
czoido Apr 5, 2021
f1f4259
add some unit tests
czoido Apr 6, 2021
02c163d
remove translate
czoido Apr 6, 2021
6a9499f
revert changes
czoido Apr 6, 2021
45929da
revert changes
czoido Apr 6, 2021
90e578c
revert changes
czoido Apr 6, 2021
7121b3d
use other properties names
czoido Apr 6, 2021
8cf1d7c
update tests
czoido Apr 6, 2021
eaeb0c4
fix filename
czoido Apr 6, 2021
06b0654
not bad
lasote Apr 6, 2021
eda93bb
Merge remote-tracking branch 'origin/develop' into feature/yyy
lasote Apr 6, 2021
e5aa0ac
review
lasote Apr 6, 2021
7e287c6
fix gets
czoido Apr 6, 2021
8aaa18c
add tests
czoido Apr 6, 2021
c5b4869
fix test
czoido Apr 6, 2021
2fa20cd
add note
czoido Apr 6, 2021
547b636
test multi
czoido Apr 6, 2021
65d29c3
move to integration
czoido Apr 6, 2021
bd839b3
fix name
czoido Apr 6, 2021
95a7d79
revert change
czoido Apr 6, 2021
cc89990
Merge branch 'develop' of github.com:conan-io/conan into feature/chan…
czoido Apr 6, 2021
491cc83
add more tests
czoido Apr 6, 2021
d83e979
remove argument
czoido Apr 6, 2021
fb33a21
Fix win test
lasote Apr 7, 2021
85932a4
review
czoido Apr 7, 2021
97df85e
review
czoido Apr 7, 2021
e74d73c
minor refactor
czoido Apr 7, 2021
3f3f634
Review
lasote Apr 7, 2021
105c556
Removed patterns vars
lasote Apr 7, 2021
d07a8bc
Fixed tests
lasote Apr 8, 2021
a7851e2
change name
czoido Apr 12, 2021
1813fb4
Remove import
lasote Apr 13, 2021
d8b0302
Merge branch 'feature/change_cpp_info_syntax' into feature/yyy_2
lasote Apr 13, 2021
9304737
Test passing
lasote Apr 15, 2021
6bbcca3
Merged develop
lasote Apr 15, 2021
469ab56
Adadpter CMakeDeps
lasote Apr 15, 2021
ba2e288
removed version access
lasote Apr 15, 2021
3b1dca3
lines
lasote Apr 15, 2021
bf9ea00
Fixed tests
lasote Apr 15, 2021
da565a9
PEPOCHO
lasote Apr 15, 2021
d385903
print
lasote Apr 16, 2021
7c7b49e
Mock
lasote Apr 16, 2021
17b0d6d
Merge remote-tracking branch 'origin/develop' into feature/yyy
lasote Apr 16, 2021
e2e5867
traces for test
lasote Apr 16, 2021
80218c3
more asserts
lasote Apr 16, 2021
1212780
traces
lasote Apr 16, 2021
7304b82
try host only
lasote Apr 16, 2021
50a6ec8
Replace path windows
lasote Apr 16, 2021
2a2ac07
Merged develop
lasote Apr 19, 2021
338aedd
Default get name to old mechanism
lasote Apr 19, 2021
f5c7a1b
Merge branch 'develop' into feature/yyy
memsharded Apr 19, 2021
af03ac3
review
lasote Apr 20, 2021
6263e09
Merge branch 'feature/yyy' of github.com:lasote/conan into feature/yyy
lasote Apr 20, 2021
c4f6360
Renamed var
lasote Apr 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
270 changes: 136 additions & 134 deletions conan/tools/cmake/cmakedeps.py

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions conans/model/conan_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from conans.model.build_info import DepsCppInfo
from conans.model.env_info import DepsEnvInfo
from conans.model.layout import Layout
from conans.model.new_build_info import NewCppInfo
from conans.model.options import Options, OptionsValues, PackageOptions
from conans.model.requires import Requirements
from conans.model.user_info import DepsUserInfo
Expand Down Expand Up @@ -156,6 +157,8 @@ def __init__(self, output, runner, display_name="", user=None, channel=None):
self._conan_node = None # access to container Node object, to access info, context, deps...
self.virtualenv = True # Set to false to opt-out automatic usage of VirtualEnv

self._conan_new_cpp_info = None # Will be calculated lazy in the getter

@property
def context(self):
return self._conan_node.context
Expand Down Expand Up @@ -213,6 +216,12 @@ def initialize(self, settings, env, buildenv=None):
if self.description is not None and not isinstance(self.description, six.string_types):
raise ConanException("Recipe 'description' must be a string.")

@property
def new_cpp_info(self):
if not self._conan_new_cpp_info:
self._conan_new_cpp_info = NewCppInfo.from_old_cppinfo(self.cpp_info)
return self._conan_new_cpp_info

@property
def source_folder(self):
return self.layout.source_folder
Expand Down
8 changes: 8 additions & 0 deletions conans/model/conanfile_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ def __eq__(self, other):
def __ne__(self, other):
return not self.__eq__(other)

@property
def package_folder(self):
return self._conanfile.package_folder

@property
def ref(self):
return self._conanfile.ref
Expand All @@ -41,6 +45,10 @@ def runenv_info(self):
def cpp_info(self):
return self._conanfile.cpp_info

@property
def new_cpp_info(self):
return self._conanfile.new_cpp_info

@property
def settings(self):
return self._conanfile.settings
Expand Down
169 changes: 169 additions & 0 deletions conans/model/new_build_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import copy
lasote marked this conversation as resolved.
Show resolved Hide resolved
from collections import OrderedDict

from conans.errors import ConanException
from conans.model.build_info import DefaultOrderedDict

_DIRS_VAR_NAMES = ["includedirs", "srcdirs", "libdirs", "resdirs", "bindirs", "builddirs",
"frameworkdirs"]
_FIELD_VAR_NAMES = ["system_libs", "frameworks", "libs", "defines", "cflags", "cxxflags",
"sharedlinkflags", "exelinkflags"]


class _NewComponent(object):

def __init__(self):

# ###### PROPERTIES
self._generator_properties = {}

# ###### DIRECTORIES
self.includedirs = [] # Ordered list of include paths
self.srcdirs = [] # Ordered list of source paths
self.libdirs = [] # Directories to find libraries
self.resdirs = [] # Directories to find resources, data, etc
self.bindirs = [] # Directories to find executables and shared libs
self.builddirs = []
self.frameworkdirs = []

# ##### FIELDS
self.system_libs = [] # Ordered list of system libraries
self.frameworks = [] # Macos .framework
self.libs = [] # The libs to link against
self.defines = [] # preprocessor definitions
self.cflags = [] # pure C flags
self.cxxflags = [] # C++ compilation flags
self.sharedlinkflags = [] # linker flags
self.exelinkflags = [] # linker flags

self.sysroot = ""
self.requires = []

@property
def required_component_names(self):
""" Names of the required components of the same package (not scoped with ::)"""
return [r for r in self.requires if "::" not in r]

def set_property(self, property_name, value, generator=None):
self._generator_properties.setdefault(generator, {})[property_name] = value

def get_property(self, property_name, generator=None):
if generator:
try:
return self._generator_properties[generator][property_name]
except KeyError:
pass
try:
return self._generator_properties[None][property_name]
except KeyError:
pass


class NewCppInfo(object):

def __init__(self):
super(NewCppInfo, self).__init__()
self.components = DefaultOrderedDict(lambda: _NewComponent())
self.components[None] = _NewComponent() # Main package is a component with None key

def __getattr__(self, attr):
return getattr(self.components[None], attr)

def __setattr__(self, attr, value):
if attr in ["components"]:
super(NewCppInfo, self).__setattr__(attr, value)
else:
setattr(self.components[None], attr, value)

@property
def has_components(self):
return len(self.components) > 1

@staticmethod
def from_old_cppinfo(old):
ret = NewCppInfo()
for varname in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
setattr(ret, varname, getattr(old, varname))

ret._generator_properties = copy.copy(old._generator_properties)

# COMPONENTS
for cname, c in old.components.items():
for varname in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
setattr(ret.components[cname], varname, getattr(c, varname))
ret.components[cname].requires = copy.copy(c.requires)
ret.components[cname]._generator_properties = copy.copy(c._generator_properties)
return ret

def get_sorted_components(self):
"""Order the components taking into account if they depend on another component in the
same package (not scoped with ::). First less dependant
return: {component_name: component}
"""
processed = [] # Names of the components ordered
# FIXME: Cache the sort
while (len(self.components) - 1) > len(processed):
for name, c in self.components.items():
if name is None:
continue
req_processed = [n for n in c.required_component_names if n not in processed]
if not req_processed and name not in processed:
processed.append(name)

return OrderedDict([(cname, self.components[cname]) for cname in processed])

def aggregate_components(self):
"""Aggregates all the components as global values"""
if self.has_components:
components = self.get_sorted_components()
cnames = list(components.keys())
cnames.reverse() # More dependant first

# Clean global values
for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
setattr(self.components[None], n, [])

for name in cnames:
component = components[name]
for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
dest = getattr(self.components[None], n)
dest += [i for i in getattr(component, n) if i not in dest]
self.components[None].requires.extend(component.requires)
# The generator properties are not aggregated, should be defined in the root
# cpp info if needed
# FIXME: What to do about sysroot?
# Leave only the aggregated value
main_value = self.components[None]
self.components = DefaultOrderedDict(lambda: _NewComponent())
self.components[None] = main_value

def merge(self, other):
# TODO: Still not used, to be used by global generators
# If we are merging isolated cppinfo objects is because the generator is "global"
# (dirs and flags in link order in a single list) so first call
# cpp_info.aggregate_components()
if self.has_components or other.has_components:
raise ConanException("Cannot aggregate two cppinfo objects with components. "
"Do cpp_info.aggregate_components() first")
for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
dest = getattr(self.components[None], n)
dest += [i for i in getattr(other, n) if i not in dest]

def copy(self):
ret = NewCppInfo()
ret._generator_properties = copy.copy(self._generator_properties)
ret.components = DefaultOrderedDict(lambda: _NewComponent())
for comp_name in self.components:
ret.components[comp_name] = copy.copy(self.components[comp_name])
return ret

@property
def required_components(self):
"""Returns a list of tuples with (require, component_name) required by the package
If the require is internal (to another component), the require will be None"""
# FIXME: Cache the value
ret = []
for comp in self.components.values():
ret.extend([r.split("::") for r in comp.requires if "::" in r and r not in ret])
ret.extend([(None, r) for r in comp.requires if "::" not in r and r not in ret])
return ret
163 changes: 163 additions & 0 deletions conans/test/functional/conan_build_info/new_build_info_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import pytest

from conans.errors import ConanException
from conans.model.build_info import CppInfo
from conans.model.new_build_info import NewCppInfo, _DIRS_VAR_NAMES, _FIELD_VAR_NAMES


def test_components_order():
cppinfo = NewCppInfo()
cppinfo.components["c1"].requires = ["c4", "OtherPackage::OtherComponent2"]
cppinfo.components["c2"].requires = ["OtherPackage::OtherComponent"]
cppinfo.components["c3"].requires = ["c2"]
cppinfo.components["c4"].requires = ["c3"]
sorted_c = list(cppinfo.get_sorted_components().keys())
assert sorted_c == ["c2", "c3", "c4", "c1"]


def test_generator_properties_copy():
cppinfo = NewCppInfo()
cppinfo.set_property("foo", "foo_value", "generator1")
cppinfo.set_property("foo", "var_value", "generator2")
cppinfo.set_property("foo2", "foo2_value", "generator1")

copied = cppinfo.copy()

assert copied.get_property("foo") is None
assert copied.get_property("foo", "generator1") == "foo_value"
assert copied.get_property("foo", "generator2") == "var_value"


def test_component_aggregation():
cppinfo = NewCppInfo()

cppinfo.includedirs = ["includedir"]
cppinfo.libdirs = ["libdir"]
cppinfo.srcdirs = ["srcdir"]
cppinfo.bindirs = ["bindir"]
cppinfo.builddirs = ["builddir"]
cppinfo.frameworkdirs = ["frameworkdir"]

cppinfo.components["c2"].includedirs = ["includedir_c2"]
cppinfo.components["c2"].libdirs = ["libdir_c2"]
cppinfo.components["c2"].srcdirs = ["srcdir_c2"]
cppinfo.components["c2"].bindirs = ["bindir_c2"]
cppinfo.components["c2"].builddirs = ["builddir_c2"]
cppinfo.components["c2"].frameworkdirs = ["frameworkdir_c2"]
cppinfo.components["c2"].cxxflags = ["cxxflags_c2"]
cppinfo.components["c2"].defines = ["defines_c2"]

cppinfo.components["c1"].requires = ["c2", "LIB_A::C1"]
cppinfo.components["c1"].includedirs = ["includedir_c1"]
cppinfo.components["c1"].libdirs = ["libdir_c1"]
cppinfo.components["c1"].srcdirs = ["srcdir_c1"]
cppinfo.components["c1"].bindirs = ["bindir_c1"]
cppinfo.components["c1"].builddirs = ["builddir_c1"]
cppinfo.components["c1"].frameworkdirs = ["frameworkdir_c1"]
cppinfo.components["c1"].cxxflags = ["cxxflags_c1"]
cppinfo.components["c1"].defines = ["defines_c1"]

ret = cppinfo.copy()
ret.aggregate_components()

assert ret.includedirs == ["includedir_c1", "includedir_c2"]
assert ret.libdirs == ["libdir_c1", "libdir_c2"]
assert ret.srcdirs == ["srcdir_c1", "srcdir_c2"]
assert ret.bindirs == ["bindir_c1", "bindir_c2"]
assert ret.builddirs == ["builddir_c1", "builddir_c2"]
assert ret.frameworkdirs == ["frameworkdir_c1", "frameworkdir_c2"]
assert ret.cxxflags == ["cxxflags_c1", "cxxflags_c2"]
assert ret.defines == ["defines_c1", "defines_c2"]

# If we change the internal graph the order is different
cppinfo.components["c1"].requires = []
cppinfo.components["c2"].requires = ["c1"]

ret = cppinfo.copy()
ret.aggregate_components()

assert ret.includedirs == ["includedir_c2", "includedir_c1"]
assert ret.libdirs == ["libdir_c2", "libdir_c1"]
assert ret.srcdirs == ["srcdir_c2", "srcdir_c1"]
assert ret.bindirs == ["bindir_c2", "bindir_c1"]
assert ret.builddirs == ["builddir_c2", "builddir_c1"]
assert ret.frameworkdirs == ["frameworkdir_c2", "frameworkdir_c1"]


def norm(paths):
return [d.replace("\\", "/") for d in paths]


def test_cpp_info_merge_with_components():
"""If we try to merge a cpp info with another one and some of them have components, assert"""
cppinfo = NewCppInfo()
cppinfo.components["foo"].cxxflags = ["var"]

other = NewCppInfo()
other.components["foo2"].cxxflags = ["var2"]

with pytest.raises(ConanException) as exc:
cppinfo.merge(other)

assert "Cannot aggregate two cppinfo objects with components" in str(exc.value)


def test_cpp_info_merge_aggregating_components_first():
cppinfo = NewCppInfo()
for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
setattr(cppinfo.components["foo"], n, ["var_{}_1".format(n), "var_{}_2".format(n)])
setattr(cppinfo.components["foo2"], n, ["var2_{}_1".format(n), "var2_{}_2".format(n)])

cppinfo.components["foo"].requires = ["foo2"] # Deterministic order

other = NewCppInfo()
for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
setattr(other.components["boo"], n, ["jar_{}_1".format(n), "jar_{}_2".format(n)])
setattr(other.components["boo2"], n, ["jar2_{}_1".format(n), "jar2_{}_2".format(n)])

other.components["boo"].requires = ["boo2"] # Deterministic order

cppinfo.aggregate_components()
other.aggregate_components()

cppinfo.merge(other)

for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
assert getattr(cppinfo, n) == ["var_{}_1".format(n), "var_{}_2".format(n),
"var2_{}_1".format(n), "var2_{}_2".format(n),
"jar_{}_1".format(n), "jar_{}_2".format(n),
"jar2_{}_1".format(n), "jar2_{}_2".format(n)]


def test_from_old_cppinfo_components():
oldcppinfo = CppInfo("ref", "/root/")
for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
setattr(oldcppinfo.components["foo"], n, ["var_{}_1".format(n), "var_{}_2".format(n)])
setattr(oldcppinfo.components["foo2"], n, ["var2_{}_1".format(n), "var2_{}_2".format(n)])

# The names and filenames are not copied to the new model
oldcppinfo.components["foo"].names["Gen"] = ["MyName"]
oldcppinfo.filenames["Gen"] = ["Myfilename"]

cppinfo = NewCppInfo.from_old_cppinfo(oldcppinfo)

assert isinstance(cppinfo, NewCppInfo)

for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
assert getattr(cppinfo.components["foo"], n) == ["var_{}_1".format(n),
"var_{}_2".format(n)]
assert getattr(cppinfo.components["foo2"], n) == ["var2_{}_1".format(n),
"var2_{}_2".format(n)]


def test_from_old_cppinfo_no_components():
oldcppinfo = CppInfo("ref", "/root/")
for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
setattr(oldcppinfo, n, ["var_{}_1".format(n), "var_{}_2".format(n)])

cppinfo = NewCppInfo.from_old_cppinfo(oldcppinfo)

assert isinstance(cppinfo, NewCppInfo)

for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:
assert getattr(cppinfo, n) == ["var_{}_1".format(n), "var_{}_2".format(n)]