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

Specify build modules by the generator in cpp_info #8232

Merged
merged 23 commits into from
Jan 11, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
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
20 changes: 10 additions & 10 deletions conans/client/generators/cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@


class DepsCppCmake(object):
def __init__(self, cpp_info):
def __init__(self, cpp_info, generator_name):
def join_paths(paths):
"""
Paths are doubled quoted, and escaped (but spaces)
e.g: set(LIBFOO_INCLUDE_DIRS "/path/to/included/dir" "/path/to/included/dir2")
"""

return "\n\t\t\t".join('"%s"'
% p.replace('\\', '/').replace('$', '\\$').replace('"', '\\"')
for p in paths)
Expand Down Expand Up @@ -63,11 +62,12 @@ def join_paths_single_var(values):
self.exelinkflags_list = join_flags(";", cpp_info.exelinkflags)

self.rootpath = join_paths([cpp_info.rootpath])
self.build_modules_paths = join_paths([path for path in cpp_info.build_modules_paths if
path.endswith(".cmake")])
self.build_modules_paths = join_paths(cpp_info.build_modules_paths.get(generator_name, ""))
danimtb marked this conversation as resolved.
Show resolved Hide resolved


class CMakeGenerator(Generator):
name = "cmake"

@property
def filename(self):
return BUILD_INFO_CMAKE
Expand All @@ -79,13 +79,13 @@ def content(self):

# Per requirement variables
for _, dep_cpp_info in self.deps_build_info.dependencies:
dep_name = dep_cpp_info.get_name("cmake")
deps = DepsCppCmake(dep_cpp_info)
dep_name = dep_cpp_info.get_name(self.name)
deps = DepsCppCmake(dep_cpp_info, self.name)
dep_flags = cmake_dependency_vars(dep_name, deps=deps)
sections.append(dep_flags)

for config, cpp_info in dep_cpp_info.configs.items():
deps = DepsCppCmake(cpp_info)
deps = DepsCppCmake(cpp_info, self.name)
dep_flags = cmake_dependency_vars(dep_name, deps=deps, build_type=config)
sections.append(dep_flags)

Expand All @@ -96,17 +96,17 @@ def content(self):
sections.append(cmake_settings_info(self.conanfile.settings))
all_flags = cmake_dependencies(dependencies=self.deps_build_info.deps)
sections.append(all_flags)
deps = DepsCppCmake(self.deps_build_info)
deps = DepsCppCmake(self.deps_build_info, self.name)
all_flags = cmake_global_vars(deps=deps)
sections.append(all_flags)

for config, cpp_info in self.deps_build_info.configs.items():
deps = DepsCppCmake(cpp_info)
deps = DepsCppCmake(cpp_info, self.name)
dep_flags = cmake_global_vars(deps=deps, build_type=config)
sections.append(dep_flags)

# TARGETS
sections.extend(generate_targets_section(self.deps_build_info.dependencies, "cmake"))
sections.extend(generate_targets_section(self.deps_build_info.dependencies, self.name))

# MACROS
sections.append(cmake_macros)
Expand Down
6 changes: 3 additions & 3 deletions conans/client/generators/cmake_find_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def _get_components(self, pkg_name, cpp_info):
components = super(CMakeFindPackageGenerator, self)._get_components(pkg_name, cpp_info)
ret = []
for comp_genname, comp, comp_requires_gennames in components:
deps_cpp_cmake = DepsCppCmake(comp)
deps_cpp_cmake = DepsCppCmake(comp, self.name)
deps_cpp_cmake.public_deps = " ".join(
["{}::{}".format(*it) for it in comp_requires_gennames])
ret.append((comp_genname, deps_cpp_cmake))
Expand All @@ -253,7 +253,7 @@ def _find_for_dep(self, pkg_name, pkg_findname, pkg_filename, cpp_info):
# Note these are in reversed order, from more dependent to less dependent
pkg_components = " ".join(["{p}::{c}".format(p=pkg_findname, c=comp_findname) for
comp_findname, _ in reversed(components)])
pkg_info = DepsCppCmake(cpp_info)
pkg_info = DepsCppCmake(cpp_info, self.name)
global_target_variables = target_template.format(name=pkg_findname, deps=pkg_info,
build_type_suffix="",
deps_names=deps_names)
Expand Down Expand Up @@ -283,7 +283,7 @@ def _find_for_dep(self, pkg_name, pkg_findname, pkg_filename, cpp_info):
dep_cpp_info = extend(dep_cpp_info, build_type.lower())

# The find_libraries_block, all variables for the package, and creation of targets
deps = DepsCppCmake(dep_cpp_info)
deps = DepsCppCmake(dep_cpp_info, self.name)
find_libraries_block = target_template.format(name=pkg_findname, deps=deps,
build_type_suffix="",
deps_names=deps_names)
Expand Down
4 changes: 2 additions & 2 deletions conans/client/generators/cmake_find_package_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,14 +309,14 @@ def content(self):

# If any config matches the build_type one, add it to the cpp_info
dep_cpp_info = extend(cpp_info, build_type.lower())
deps = DepsCppCmake(dep_cpp_info)
deps = DepsCppCmake(dep_cpp_info, self.name)
find_lib = target_template.format(name=pkg_findname, deps=deps,
build_type_suffix=build_type_suffix,
deps_names=deps_names)
ret["{}Target-{}.cmake".format(pkg_filename, self.configuration.lower())] = find_lib
else:
cpp_info = extend(cpp_info, build_type.lower())
pkg_info = DepsCppCmake(cpp_info)
pkg_info = DepsCppCmake(cpp_info, self.name)
components = self._get_components(pkg_name, cpp_info)
# Note these are in reversed order, from more dependent to less dependent
pkg_components = " ".join(["{p}::{c}".format(p=pkg_findname, c=comp_findname) for
Expand Down
14 changes: 8 additions & 6 deletions conans/client/generators/cmake_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
cmake_package_info, cmake_user_info_vars,
generate_targets_section, CMakeCommonMacros)
from conans.model import Generator
from conans.model.build_info import CppInfo
from conans.model.build_info import CppInfo, merge_dicts


def extend(cpp_info, config):
Expand All @@ -14,6 +14,7 @@ def extend(cpp_info, config):
if config_info:
def add_lists(seq1, seq2):
return seq1 + [s for s in seq2 if s not in seq1]

result = CppInfo(str(config_info), config_info.rootpath)
result.filter_empty = cpp_info.filter_empty
result.includedirs = add_lists(cpp_info.includedirs, config_info.includedirs)
Expand All @@ -28,12 +29,13 @@ def add_lists(seq1, seq2):
result.sharedlinkflags = cpp_info.sharedlinkflags + config_info.sharedlinkflags
result.exelinkflags = cpp_info.exelinkflags + config_info.exelinkflags
result.system_libs = add_lists(cpp_info.system_libs, config_info.system_libs)
result.build_modules = add_lists(cpp_info.build_modules, config_info.build_modules)
result.build_modules = merge_dicts(cpp_info.build_modules, config_info.build_modules)
return result
return cpp_info


class CMakeMultiGenerator(Generator):
name = "cmake_multi"

@property
def content(self):
Expand All @@ -51,10 +53,10 @@ def _content_type(self, build_type):

# Per requirement variables
for _, dep_cpp_info in self.deps_build_info.dependencies:
dep_name = dep_cpp_info.get_name("cmake_multi")
dep_name = dep_cpp_info.get_name(self.name)
# Only the specific of the build_type
dep_cpp_info = extend(dep_cpp_info, build_type)
deps = DepsCppCmake(dep_cpp_info)
deps = DepsCppCmake(dep_cpp_info, self.name)
dep_flags = cmake_dependency_vars(dep_name, deps=deps, build_type=build_type)
sections.append(dep_flags)

Expand All @@ -65,7 +67,7 @@ def _content_type(self, build_type):
sections.append(all_flags)

dep_cpp_info = extend(self.deps_build_info, build_type)
deps = DepsCppCmake(dep_cpp_info)
deps = DepsCppCmake(dep_cpp_info, self.name)
all_flags = cmake_global_vars(deps=deps, build_type=build_type)
sections.append(all_flags)

Expand All @@ -84,7 +86,7 @@ def _content_multi(self):
version=self.conanfile.version))

# TARGETS
sections.extend(generate_targets_section(self.deps_build_info.dependencies, "cmake_multi"))
sections.extend(generate_targets_section(self.deps_build_info.dependencies, self.name))
# MACROS
sections.append(cmake_macros_multi)

Expand Down
8 changes: 5 additions & 3 deletions conans/client/generators/cmake_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


class CMakePathsGenerator(Generator):
name = "cmake_paths"

@property
def filename(self):
Expand All @@ -15,16 +16,17 @@ def content(self):
# in a package could have been "patched" with the `cmake.patch_config_paths()`
# replacing absolute paths with CONAN_XXX_ROOT variables.
for _, dep_cpp_info in self.deps_build_info.dependencies:
var_name = "CONAN_{}_ROOT".format(dep_cpp_info.get_name("cmake_paths").upper())
lines.append('set({} {})'.format(var_name, DepsCppCmake(dep_cpp_info).rootpath))
var_name = "CONAN_{}_ROOT".format(dep_cpp_info.get_name(self.name).upper())
lines.append('set({} {})'.format(var_name, DepsCppCmake(dep_cpp_info,
self.name).rootpath))

# We want to prioritize the FindXXX.cmake files:
# 1. First the files found in the packages
# 2. The previously set (by default CMAKE_MODULE_PATH is empty)
# 3. The "install_folder" ones, in case there is no FindXXX.cmake, try with the install dir
# if the user used the "cmake_find_package" will find the auto-generated
# 4. The CMake installation dir/Modules ones.
deps = DepsCppCmake(self.deps_build_info)
deps = DepsCppCmake(self.deps_build_info, self.name)
lines.append("set(CMAKE_MODULE_PATH {deps.build_paths} ${{CMAKE_MODULE_PATH}} "
"${{CMAKE_CURRENT_LIST_DIR}})".format(deps=deps))
lines.append("set(CMAKE_PREFIX_PATH {deps.build_paths} ${{CMAKE_PREFIX_PATH}} "
Expand Down
72 changes: 66 additions & 6 deletions conans/model/build_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,56 @@ def __copy__(self):
return the_copy


class BuildModulesDict(dict):
"""
A dictionary with append and extend for cmake build modules to keep it backwards compatible
with the list interface
"""

def __getitem__(self, key):
if key not in self.keys():
super(BuildModulesDict, self).__setitem__(key, list())
return super(BuildModulesDict, self).__getitem__(key)

def append(self, item):
if item.endswith(".cmake"):
self["cmake"].append(item)
self["cmake_multi"].append(item)
self["cmake_find_package"].append(item)
self["cmake_find_package_multi"].append(item)
danimtb marked this conversation as resolved.
Show resolved Hide resolved

def extend(self, items):
for item in items:
self.append(item)

@classmethod
def from_list(cls, build_modules):
the_dict = BuildModulesDict({"cmake": [], "cmake_multi": [], "cmake_find_package": [],
"cmake_find_package_multi": []})
for item in build_modules:
if item.endswith(".cmake"):
for val in the_dict.values():
val.append(item)
danimtb marked this conversation as resolved.
Show resolved Hide resolved
return the_dict

def to_abs_paths(self, rootpath):
for generator, values in self.items():
self[generator] = [os.path.join(rootpath, p) if not os.path.isabs(p) else p
for p in values]
danimtb marked this conversation as resolved.
Show resolved Hide resolved


def merge_dicts(d1, d2):
def merge_lists(seq1, seq2):
return [s for s in seq1 if s not in seq2] + seq2
result = d1.copy()
for k, v in d2.items():
if k not in d1.keys():
result[k] = v
else:
result[k] = merge_lists(d1[k], d2[k])
return result


class _CppInfo(object):
""" Object that stores all the necessary information to build in C/C++.
It is intended to be system independent, translation to
Expand All @@ -60,7 +110,7 @@ def __init__(self):
self.cxxflags = [] # C++ compilation flags
self.sharedlinkflags = [] # linker flags
self.exelinkflags = [] # linker flags
self.build_modules = []
self.build_modules = BuildModulesDict() # FIXME: This should be just a plain dict
self.filenames = {} # name of filename to create for various generators
self.rootpath = ""
self.sysroot = ""
Expand Down Expand Up @@ -89,8 +139,10 @@ def _filter_paths(self, paths):
@property
def build_modules_paths(self):
if self._build_modules_paths is None:
self._build_modules_paths = [os.path.join(self.rootpath, p) if not os.path.isabs(p)
else p for p in self.build_modules]
if isinstance(self.build_modules, list): # FIXME: This should be just a plain dict
self.build_modules = BuildModulesDict.from_list(self.build_modules)
self._build_modules_paths = self.build_modules
self._build_modules_paths.to_abs_paths(self.rootpath)
return self._build_modules_paths

@property
Expand Down Expand Up @@ -320,6 +372,7 @@ def __init__(self):
super(_BaseDepsCppInfo, self).__init__()

def update(self, dep_cpp_info):

def merge_lists(seq1, seq2):
return [s for s in seq1 if s not in seq2] + seq2

Expand All @@ -333,7 +386,7 @@ def merge_lists(seq1, seq2):
self.frameworkdirs = merge_lists(self.frameworkdirs, dep_cpp_info.framework_paths)
self.libs = merge_lists(self.libs, dep_cpp_info.libs)
self.frameworks = merge_lists(self.frameworks, dep_cpp_info.frameworks)
self.build_modules = merge_lists(self.build_modules, dep_cpp_info.build_modules_paths)
self.build_modules = merge_dicts(self.build_modules, dep_cpp_info.build_modules_paths)
danimtb marked this conversation as resolved.
Show resolved Hide resolved
danimtb marked this conversation as resolved.
Show resolved Hide resolved
self.requires = merge_lists(self.requires, dep_cpp_info.requires)
self.rootpaths.append(dep_cpp_info.rootpath)

Expand Down Expand Up @@ -401,7 +454,7 @@ def __init__(self, cpp_info):
self._res_paths = None
self._src_paths = None
self._framework_paths = None
self._build_module_paths = None
self._build_modules_paths = None
self._sorted_components = None
self._check_component_requires()

Expand Down Expand Up @@ -488,7 +541,14 @@ def _get_sorted_components(self):

@property
def build_modules_paths(self):
return self._aggregated_paths("build_modules")
if self._build_modules_paths is not None:
return self._build_modules_paths
paths = self._cpp_info.build_modules_paths
if self._cpp_info.components:
for component in self._get_sorted_components().values():
paths = merge_dicts(paths, component.build_modules_paths)
self._build_modules_paths = paths
return self._build_modules_paths

@property
def include_paths(self):
Expand Down
4 changes: 2 additions & 2 deletions conans/test/functional/generators/cmake_find_package_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ def package_info(self):
""")
# This is a module that defines some functionality
find_module = textwrap.dedent("""
function(conan_message MESSAGE_OUTPUT)
function(custom_message MESSAGE_OUTPUT)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to avoid using conan_message() defined by the generator

message(${ARGV${0}})
endfunction()
""")
Expand Down Expand Up @@ -424,7 +424,7 @@ def build(self):
cmake_minimum_required(VERSION 3.0)
project(test)
find_package(test)
conan_message("Printing using a external module!")
custom_message("Printing using a external module!")
""")
client.save({"conanfile.py": consumer, "CMakeLists.txt": cmakelists})
client.run("create .")
Expand Down