From 650ca9419d49d7e0becf04b4ee40cef23d097ef2 Mon Sep 17 00:00:00 2001 From: danimtb Date: Tue, 26 May 2020 17:42:46 +0200 Subject: [PATCH 01/35] Add jinja2 template for cmake_find_package with components --- .../client/generators/cmake_find_package.py | 298 +++++++++++++++--- conans/model/build_info.py | 1 + 2 files changed, 258 insertions(+), 41 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 63eac0e0bb8..b439da92979 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -1,10 +1,13 @@ +from jinja2 import Template import textwrap from conans.client.generators.cmake import DepsCppCmake from conans.client.generators.cmake_find_package_common import (target_template, CMakeFindPackageCommonMacros, - find_transitive_dependencies) + find_transitive_dependencies, + target_template_info) from conans.client.generators.cmake_multi import extend +from conans.errors import ConanException from conans.model import Generator @@ -43,6 +46,171 @@ class CMakeFindPackageGenerator(Generator): endif() """) + find_components_tpl = Template(textwrap.dedent(""" + ########## MACROS ########################################################################### + {% raw %} + function(conan_message MESSAGE_OUTPUT) + if(NOT CONAN_CMAKE_SILENT_OUTPUT) + message(${ARGV${0}}) + endif() + endfunction() + + macro(conan_find_apple_frameworks FRAMEWORKS_FOUND FRAMEWORKS FRAMEWORKS_DIRS) + if(APPLE) + foreach(_FRAMEWORK ${FRAMEWORKS}) + # https://cmake.org/pipermail/cmake-developers/2017-August/030199.html + find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAME ${_FRAMEWORK} PATHS ${FRAMEWORKS_DIRS}) + if(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND) + list(APPEND ${FRAMEWORKS_FOUND} ${CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND}) + else() + message(FATAL_ERROR "Framework library ${_FRAMEWORK} not found in paths: ${FRAMEWORKS_DIRS}") + endif() + endforeach() + endif() + endmacro() + + function(conan_package_library_targets libraries package_libdir deps out_libraries out_libraries_target build_type package_name) + unset(_CONAN_ACTUAL_TARGETS CACHE) + unset(_CONAN_FOUND_SYSTEM_LIBS CACHE) + foreach(_LIBRARY_NAME ${libraries}) + find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${package_libdir} + NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + if(CONAN_FOUND_LIBRARY) + conan_message(STATUS "Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}") + list(APPEND _out_libraries ${CONAN_FOUND_LIBRARY}) + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") + # Create a micro-target for each lib/a found + set(_LIB_NAME CONAN_LIB::${package_name}_${_LIBRARY_NAME}${build_type}) + if(NOT TARGET ${_LIB_NAME}) + # Create a micro-target for each lib/a found + add_library(${_LIB_NAME} UNKNOWN IMPORTED) + set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION ${CONAN_FOUND_LIBRARY}) + set(_CONAN_ACTUAL_TARGETS ${_CONAN_ACTUAL_TARGETS} ${_LIB_NAME}) + else() + conan_message(STATUS "Skipping already existing target: ${_LIB_NAME}") + endif() + list(APPEND _out_libraries_target ${_LIB_NAME}) + endif() + conan_message(STATUS "Found: ${CONAN_FOUND_LIBRARY}") + else() + conan_message(STATUS "Library ${_LIBRARY_NAME} not found in package, might be system one") + list(APPEND _out_libraries_target ${_LIBRARY_NAME}) + list(APPEND _out_libraries ${_LIBRARY_NAME}) + set(_CONAN_FOUND_SYSTEM_LIBS "${_CONAN_FOUND_SYSTEM_LIBS};${_LIBRARY_NAME}") + endif() + unset(CONAN_FOUND_LIBRARY CACHE) + endforeach() + + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") + # Add all dependencies to all targets + string(REPLACE " " ";" deps_list "${deps}") + foreach(_CONAN_ACTUAL_TARGET ${_CONAN_ACTUAL_TARGETS}) + set_property(TARGET ${_CONAN_ACTUAL_TARGET} PROPERTY INTERFACE_LINK_LIBRARIES "${_CONAN_FOUND_SYSTEM_LIBS};${deps_list}") + endforeach() + endif() + + set(${out_libraries} ${_out_libraries} PARENT_SCOPE) + set(${out_libraries_target} ${_out_libraries_target} PARENT_SCOPE) + endfunction() + {% endraw %} + ############################################################################################# + + + ########### FOUND ########################################################################### + + include(FindPackageHandleStandardArgs) + + conan_message(STATUS "Conan: Using autogenerated Find{{ pkg_name }}.cmake") + # Global approach + set({{ pkg_name }}_FOUND 1) + set({{ pkg_name }}_VERSION "{{ pkg_version }}") + + find_package_handle_standard_args({{ pkg_name }} REQUIRED_VARS + {{ pkg_name }}_VERSION VERSION_VAR {{ pkg_name }}_VERSION) + mark_as_advanced({{ pkg_name }}_FOUND {{ pkg_name }}_VERSION) + + ############################################################################################# + + + ########### COMPONENTS ###################################################################### + + {%- for comp_name, comp in components %} + + ########### COMPONENT {{ comp_name }} ####################################################### + set({{ comp_name }}_INCLUDE_DIRS {{ comp.include_paths }}) + set({{ comp_name }}_INCLUDE_DIR {{ comp.include_path }}) + set({{ comp_name }}_INCLUDES {{ comp.include_paths }}) + set({{ comp_name }}_RES_DIRS {{ comp.res_paths }}) + set({{ comp_name }}_DEFINITIONS {{ comp.defines }}) + set({{ comp_name }}_COMPILE_DEFINITIONS {{ comp.compile_definitions }}) + set({{ comp_name }}_COMPILE_OPTIONS_LIST "{{ comp.cxxflags_list }}" "{{ comp.cflags_list }}") + set({{ comp_name }}_LIBS {{ comp.libs }}) + set({{ comp_name }}_SYSTEM_LIBS {{ comp.system_libs }}) + set({{ comp_name }}_FRAMEWORK_DIRS {{ comp.framework_paths }}) + set({{ comp_name }}_FRAMEWORKS {{ comp.frameworks }}) + set({{ comp_name }}_BUILD_MODULES_PATHS {{ comp.build_modules_paths }}) + set({{ comp_name }}_DEPENDENCIES {{ comp.public_deps }}) + ############################################################################################# + + {%- endfor %} + + ############################################################################################# + + + ########## FIND PACKAGE DEPENDENCY ########################################################## + + include(CMakeFindDependencyMacro) + + {%- for public_dep in pkg_public_deps %} + if(NOT {{ public_dep }}_FOUND) + find_dependency({{ public_dep }} REQUIRED) + else() + message(STATUS "Dependency {{ public_dep }} already found") + endif() + {%- endfor %} + + ############################################################################################# + + + ########## TARGETS ########################################################################## + + {%- for comp_name, comp in components %} + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") + # Target approach + if(NOT TARGET {{ pkg_name }}::{{ comp_name }}) + add_library({{ pkg_name }}::{{ comp_name }} INTERFACE IMPORTED) + set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${% raw %}{{% endraw %}{{ comp_name }}_INCLUDE_DIRS{% raw %}}{% endraw %}") + set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_LINK_DIRECTORIES + "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}") + set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_LINK_LIBRARIES + "${% raw %}{{% endraw %}{{ comp_name }}_LIBS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}") + set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_DEFINITIONS + ${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_DEFINITIONS{% raw %}}{% endraw %}) + set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_OPTIONS + "${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_OPTIONS_LIST{% raw %}}{% endraw %}") + endif() + endif() + {%- endfor %} + + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") + if(NOT TARGET {{ pkg_name }}::{{ pkg_name }}) + add_library({{ pkg_name }}::{{ pkg_name }} INTERFACE IMPORTED) + if({{ pkg_name }}_INCLUDE_DIRS) + set_target_properties({{ pkg_name }}::{{ pkg_name }} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${% raw %}{{% endraw %}{{ pkg_name }}_INCLUDE_DIRS{% raw %}}{% endraw %}") + endif() + set_property(TARGET {{ pkg_name }}::{{ pkg_name }} PROPERTY INTERFACE_LINK_LIBRARIES + "${% raw %}{{% endraw %}{{ pkg_name }}_LIBRARIES_TARGETS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ pkg_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}") + set_property(TARGET {{ pkg_name }}::{{ pkg_name }} PROPERTY INTERFACE_COMPILE_DEFINITIONS + ${% raw %}{{% endraw %}{{ pkg_name }}_COMPILE_DEFINITIONS{% raw %}}{% endraw %}) + set_property(TARGET {{ pkg_name }}::{{ pkg_name }} PROPERTY INTERFACE_COMPILE_OPTIONS + "${% raw %}{{% endraw %}{{ pkg_name }}_COMPILE_OPTIONS_LIST{% raw %}}{% endraw %}") + endif() + endif() + ############################################################################################# + """)) + @property def filename(self): return None @@ -50,45 +218,93 @@ def filename(self): @property def content(self): ret = {} - for _, cpp_info in self.deps_build_info.dependencies: - depname = cpp_info.get_name("cmake_find_package") - ret["Find%s.cmake" % depname] = self._find_for_dep(depname, cpp_info) + for dep_name, cpp_info in self.deps_build_info.dependencies: + dep_findname = cpp_info.get_name("cmake_find_package") + ret["Find%s.cmake" % dep_findname] = self._find_for_dep(dep_name, cpp_info) return ret - def _find_for_dep(self, name, cpp_info): - # The common macros - macros_and_functions = "\n".join([ - CMakeFindPackageCommonMacros.conan_message, - CMakeFindPackageCommonMacros.apple_frameworks_macro, - CMakeFindPackageCommonMacros.conan_package_library_targets, - ]) - - # compose the cpp_info with its "debug" or "release" specific config - dep_cpp_info = cpp_info - build_type = self.conanfile.settings.get_safe("build_type") - if build_type: - dep_cpp_info = extend(dep_cpp_info, build_type.lower()) - - # The find_libraries_block, all variables for the package, and creation of targets - public_deps_names = [self.deps_build_info[dep].get_name("cmake_find_package") for dep in - dep_cpp_info.public_deps] - deps_names = ";".join(["{n}::{n}".format(n=n) for n in public_deps_names]) - - deps = DepsCppCmake(dep_cpp_info) - find_libraries_block = target_template.format(name=name, deps=deps, build_type_suffix="", - deps_names=deps_names) - - # The find_transitive_dependencies block - find_dependencies_block = "" - if dep_cpp_info.public_deps: - # Here we are generating FindXXX, so find_modules=True - f = find_transitive_dependencies(public_deps_names, find_modules=True) - # proper indentation - find_dependencies_block = ''.join(" " + line if line.strip() else line - for line in f.splitlines(True)) - - tmp = self.find_template.format(name=name, version=dep_cpp_info.version, - find_libraries_block=find_libraries_block, - find_dependencies_block=find_dependencies_block, - macros_and_functions=macros_and_functions) - return tmp + def _get_components(self, pkg_name, pkg_findname, cpp_info): + find_package_components = [] + for comp_name, comp in cpp_info._get_sorted_components().items(): + comp_findname = cpp_info.components[comp_name].get_name("cmake_find_package") + deps_cpp_cmake = DepsCppCmake(comp) + deps_cpp_cmake.public_deps = self._get_component_requires(pkg_name, pkg_findname, comp) + find_package_components.append((comp_findname, deps_cpp_cmake)) + return find_package_components + + def _get_component_requires(self, dep_name, dep_findname, comp): + comp_requires_findnames = [] + for require in comp.requires: + if "::" in require: + comp_require_dep_name = require[:require.find("::")] + if comp_require_dep_name not in self.deps_build_info.deps: + raise ConanException("Component '%s' not found: '%s' is not a package " + "requirement" % (require, comp_require_dep_name)) + comp_require_dep_findname = self.deps_build_info[comp_require_dep_name].get_name( + "cmake_find_package") + comp_require_comp_name = require[require.find("::") + 2:] + if comp_require_comp_name in self.deps_build_info.deps: + comp_require_comp_findname = comp_require_dep_findname + elif comp_require_comp_name in self.deps_build_info[comp_require_dep_name].components: + comp_require_comp_findname = self.deps_build_info[comp_require_dep_name].components[comp_require_comp_name].get_name("cmake_find_package") + else: + raise ConanException("Component '%s' not found in '%s' package requirement" + % (require, comp_require_dep_name)) + comp_requires_findnames.append("{}::{}".format(comp_require_dep_findname, comp_require_comp_findname)) + else: + comp_require_dep_findname = dep_findname + comp_require_findname = self.deps_build_info[dep_name].components[require].get_name( + "cmake_find_package") + comp_requires_findnames.append( + "{}::{}".format(comp_require_dep_findname, comp_require_findname)) + return ";".join(comp_requires_findnames) + + def _find_for_dep(self, dep_name, cpp_info): + if not cpp_info.components: + dep_findname = cpp_info.get_name("cmake_find_package") + # The common macros + macros_and_functions = "\n".join([ + CMakeFindPackageCommonMacros.conan_message, + CMakeFindPackageCommonMacros.apple_frameworks_macro, + CMakeFindPackageCommonMacros.conan_package_library_targets, + ]) + + # compose the cpp_info with its "debug" or "release" specific config + dep_cpp_info = cpp_info + build_type = self.conanfile.settings.get_safe("build_type") + if build_type: + dep_cpp_info = extend(dep_cpp_info, build_type.lower()) + + # The find_libraries_block, all variables for the package, and creation of targets + public_deps_names = [self.deps_build_info[dep].get_name("cmake_find_package") for dep in + dep_cpp_info.public_deps] + deps_names = ";".join(["{n}::{n}".format(n=n) for n in public_deps_names]) + + deps = DepsCppCmake(dep_cpp_info) + find_libraries_block = target_template.format(name=dep_findname, deps=deps, + build_type_suffix="", + deps_names=deps_names) + + # The find_transitive_dependencies block + find_dependencies_block = "" + if dep_cpp_info.public_deps: + # Here we are generating FindXXX, so find_modules=True + f = find_transitive_dependencies(public_deps_names, find_modules=True) + # proper indentation + find_dependencies_block = ''.join(" " + line if line.strip() else line + for line in f.splitlines(True)) + + tmp = self.find_template.format(name=dep_findname, version=dep_cpp_info.version, + find_libraries_block=find_libraries_block, + find_dependencies_block=find_dependencies_block, + macros_and_functions=macros_and_functions) + return tmp + else: + pkg_name = dep_name + pkg_findname = cpp_info.get_name("cmake_find_package") + return self.find_components_tpl.render( + pkg_name=pkg_findname, + pkg_version=cpp_info.version, + pkg_public_deps=[self.deps_build_info[public_dep].get_name("cmake_find_package") for + public_dep in cpp_info.public_deps], + components=self._get_components(pkg_name, pkg_findname, cpp_info)) diff --git a/conans/model/build_info.py b/conans/model/build_info.py index 1900a20ab9e..6f908f1bfae 100644 --- a/conans/model/build_info.py +++ b/conans/model/build_info.py @@ -25,6 +25,7 @@ def __init__(self, factory): def __getitem__(self, key): if key not in self.keys(): super(DefaultOrderedDict, self).__setitem__(key, self.factory()) + super(DefaultOrderedDict, self).__getitem__(key).name = key return super(DefaultOrderedDict, self).__getitem__(key) def __copy__(self): From 4090530a8b38f063d1c0fff86b0cabeb9ceb775e Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 27 May 2020 16:44:40 +0200 Subject: [PATCH 02/35] Add components to cmake_find_package --- .../client/generators/cmake_find_package.py | 194 ++++++++++-------- 1 file changed, 108 insertions(+), 86 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index b439da92979..76742575e46 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -4,14 +4,16 @@ from conans.client.generators.cmake import DepsCppCmake from conans.client.generators.cmake_find_package_common import (target_template, CMakeFindPackageCommonMacros, - find_transitive_dependencies, - target_template_info) + find_transitive_dependencies) from conans.client.generators.cmake_multi import extend from conans.errors import ConanException from conans.model import Generator +from conans.model.build_info import COMPONENT_SCOPE class CMakeFindPackageGenerator(Generator): + generator_name = "cmake_find_package" + find_template = textwrap.dedent(""" {macros_and_functions} @@ -46,8 +48,9 @@ class CMakeFindPackageGenerator(Generator): endif() """) - find_components_tpl = Template(textwrap.dedent(""" + find_components_tpl = Template(textwrap.dedent("""\ ########## MACROS ########################################################################### + ############################################################################################# {% raw %} function(conan_message MESSAGE_OUTPUT) if(NOT CONAN_CMAKE_SILENT_OUTPUT) @@ -69,23 +72,19 @@ class CMakeFindPackageGenerator(Generator): endif() endmacro() - function(conan_package_library_targets libraries package_libdir deps out_libraries out_libraries_target build_type package_name) - unset(_CONAN_ACTUAL_TARGETS CACHE) - unset(_CONAN_FOUND_SYSTEM_LIBS CACHE) + function(conan_component_library_targets out_libraries_target libdir libraries) foreach(_LIBRARY_NAME ${libraries}) - find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${package_libdir} + find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${libdir} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) if(CONAN_FOUND_LIBRARY) conan_message(STATUS "Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}") - list(APPEND _out_libraries ${CONAN_FOUND_LIBRARY}) if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") # Create a micro-target for each lib/a found - set(_LIB_NAME CONAN_LIB::${package_name}_${_LIBRARY_NAME}${build_type}) + set(_LIB_NAME ${_LIBRARY_NAME}) if(NOT TARGET ${_LIB_NAME}) # Create a micro-target for each lib/a found add_library(${_LIB_NAME} UNKNOWN IMPORTED) set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION ${CONAN_FOUND_LIBRARY}) - set(_CONAN_ACTUAL_TARGETS ${_CONAN_ACTUAL_TARGETS} ${_LIB_NAME}) else() conan_message(STATUS "Skipping already existing target: ${_LIB_NAME}") endif() @@ -93,35 +92,22 @@ class CMakeFindPackageGenerator(Generator): endif() conan_message(STATUS "Found: ${CONAN_FOUND_LIBRARY}") else() - conan_message(STATUS "Library ${_LIBRARY_NAME} not found in package, might be system one") - list(APPEND _out_libraries_target ${_LIBRARY_NAME}) - list(APPEND _out_libraries ${_LIBRARY_NAME}) - set(_CONAN_FOUND_SYSTEM_LIBS "${_CONAN_FOUND_SYSTEM_LIBS};${_LIBRARY_NAME}") + conan_message(STATUS "Library ${_LIBRARY_NAME} NOT FOUND!!") endif() unset(CONAN_FOUND_LIBRARY CACHE) endforeach() - if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") - # Add all dependencies to all targets - string(REPLACE " " ";" deps_list "${deps}") - foreach(_CONAN_ACTUAL_TARGET ${_CONAN_ACTUAL_TARGETS}) - set_property(TARGET ${_CONAN_ACTUAL_TARGET} PROPERTY INTERFACE_LINK_LIBRARIES "${_CONAN_FOUND_SYSTEM_LIBS};${deps_list}") - endforeach() - endif() - - set(${out_libraries} ${_out_libraries} PARENT_SCOPE) + conan_message(STATUS "Components Library targets: ${_out_libraries_target}") set(${out_libraries_target} ${_out_libraries_target} PARENT_SCOPE) endfunction() {% endraw %} - ############################################################################################# - - ########### FOUND ########################################################################### + ########### FOUND PACKAGE ################################################################### + ############################################################################################# include(FindPackageHandleStandardArgs) conan_message(STATUS "Conan: Using autogenerated Find{{ pkg_name }}.cmake") - # Global approach set({{ pkg_name }}_FOUND 1) set({{ pkg_name }}_VERSION "{{ pkg_version }}") @@ -129,17 +115,21 @@ class CMakeFindPackageGenerator(Generator): {{ pkg_name }}_VERSION VERSION_VAR {{ pkg_name }}_VERSION) mark_as_advanced({{ pkg_name }}_FOUND {{ pkg_name }}_VERSION) - ############################################################################################# + ########### VARIABLES ####################################################################### + ############################################################################################# - ########### COMPONENTS ###################################################################### + set({{ pkg_name }}_COMPONENTS {{ pkg_components }}) + set({{ pkg_name }}_DEPENDENCIES {{ pkg_dependencies }}) {%- for comp_name, comp in components %} - ########### COMPONENT {{ comp_name }} ####################################################### + ########### COMPONENT {{ comp_name }} VARIABLES ############################################# + set({{ comp_name }}_INCLUDE_DIRS {{ comp.include_paths }}) set({{ comp_name }}_INCLUDE_DIR {{ comp.include_path }}) set({{ comp_name }}_INCLUDES {{ comp.include_paths }}) + set({{ comp_name }}_LIB_DIRS {{ comp.lib_paths }}) set({{ comp_name }}_RES_DIRS {{ comp.res_paths }}) set({{ comp_name }}_DEFINITIONS {{ comp.defines }}) set({{ comp_name }}_COMPILE_DEFINITIONS {{ comp.compile_definitions }}) @@ -150,31 +140,60 @@ class CMakeFindPackageGenerator(Generator): set({{ comp_name }}_FRAMEWORKS {{ comp.frameworks }}) set({{ comp_name }}_BUILD_MODULES_PATHS {{ comp.build_modules_paths }}) set({{ comp_name }}_DEPENDENCIES {{ comp.public_deps }}) - ############################################################################################# {%- endfor %} - ############################################################################################# - ########## FIND PACKAGE DEPENDENCY ########################################################## + ############################################################################################# include(CMakeFindDependencyMacro) {%- for public_dep in pkg_public_deps %} + if(NOT {{ public_dep }}_FOUND) find_dependency({{ public_dep }} REQUIRED) else() message(STATUS "Dependency {{ public_dep }} already found") endif() + {%- endfor %} + + ########## FIND LIBRARIES & FRAMEWORKS / DYNAMIC VARS ####################################### ############################################################################################# + {%- for comp_name, comp in components %} + + ########## COMPONENT {{ comp_name }} FIND LIBRARIES & FRAMEWORKS / DYNAMIC VARS ############# + + set({{ comp_name }}_LIB_TARGETS "") # Will be filled later, if CMake 3 + conan_component_library_targets({{ comp_name }}_LIB_TARGETS "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_LIBS{% raw %}}{% endraw %}") + conan_message(STATUS "Components Library targets2: ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %}") + + set({{ comp_name }}_FRAMEWORKS_FOUND "") # Will be filled later + conan_find_apple_frameworks({{ comp_name }}_FRAMEWORKS_FOUND "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORK_DIRS{% raw %}}{% endraw %}") + + set({{ comp_name }}_LINK_LIBS "${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_SYSTEM_LIBS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS_FOUND{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_DEPENDENCIES{% raw %}}{% endraw %}") + + + set(CMAKE_MODULE_PATH {{ comp.build_paths }} ${CMAKE_MODULE_PATH}) + set(CMAKE_PREFIX_PATH {{ comp.build_paths }} ${CMAKE_PREFIX_PATH}) + + foreach(_BUILD_MODULE_PATH ${% raw %}{{% endraw %}{{ comp_name }}_BUILD_MODULES_PATHS{% raw %}}{% endraw %}) + include(${_BUILD_MODULE_PATH}) + endforeach() + + {%- endfor %} + ########## TARGETS ########################################################################## + ############################################################################################# {%- for comp_name, comp in components %} + + ########## COMPONENT {{ comp_name }} TARGET ################################################# + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") # Target approach if(NOT TARGET {{ pkg_name }}::{{ comp_name }}) @@ -184,84 +203,99 @@ class CMakeFindPackageGenerator(Generator): set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_LINK_DIRECTORIES "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}") set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_LINK_LIBRARIES - "${% raw %}{{% endraw %}{{ comp_name }}_LIBS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}") + "${% raw %}{{% endraw %}{{ comp_name }}_LINK_LIBS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}") set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_DEFINITIONS ${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_DEFINITIONS{% raw %}}{% endraw %}) set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_OPTIONS "${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_OPTIONS_LIST{% raw %}}{% endraw %}") endif() endif() + {%- endfor %} + ########## GLOBAL TARGET #################################################################### + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") if(NOT TARGET {{ pkg_name }}::{{ pkg_name }}) add_library({{ pkg_name }}::{{ pkg_name }} INTERFACE IMPORTED) - if({{ pkg_name }}_INCLUDE_DIRS) - set_target_properties({{ pkg_name }}::{{ pkg_name }} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${% raw %}{{% endraw %}{{ pkg_name }}_INCLUDE_DIRS{% raw %}}{% endraw %}") - endif() set_property(TARGET {{ pkg_name }}::{{ pkg_name }} PROPERTY INTERFACE_LINK_LIBRARIES - "${% raw %}{{% endraw %}{{ pkg_name }}_LIBRARIES_TARGETS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ pkg_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}") - set_property(TARGET {{ pkg_name }}::{{ pkg_name }} PROPERTY INTERFACE_COMPILE_DEFINITIONS - ${% raw %}{{% endraw %}{{ pkg_name }}_COMPILE_DEFINITIONS{% raw %}}{% endraw %}) - set_property(TARGET {{ pkg_name }}::{{ pkg_name }} PROPERTY INTERFACE_COMPILE_OPTIONS - "${% raw %}{{% endraw %}{{ pkg_name }}_COMPILE_OPTIONS_LIST{% raw %}}{% endraw %}") + "${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}") endif() endif() - ############################################################################################# + """)) @property def filename(self): return None + def _get_name(self, obj): + get_name = getattr(obj, "get_name") + return get_name(self.generator_name) + @property def content(self): ret = {} - for dep_name, cpp_info in self.deps_build_info.dependencies: - dep_findname = cpp_info.get_name("cmake_find_package") - ret["Find%s.cmake" % dep_findname] = self._find_for_dep(dep_name, cpp_info) + for pkg_name, cpp_info in self.deps_build_info.dependencies: + pkg_findname = self._get_name(cpp_info) + ret["Find%s.cmake" % pkg_findname] = self._find_for_dep(pkg_name, pkg_findname, cpp_info) return ret def _get_components(self, pkg_name, pkg_findname, cpp_info): find_package_components = [] for comp_name, comp in cpp_info._get_sorted_components().items(): - comp_findname = cpp_info.components[comp_name].get_name("cmake_find_package") + comp_findname = self._get_name(cpp_info.components[comp_name]) deps_cpp_cmake = DepsCppCmake(comp) deps_cpp_cmake.public_deps = self._get_component_requires(pkg_name, pkg_findname, comp) find_package_components.append((comp_findname, deps_cpp_cmake)) + find_package_components.reverse() # From the less dependent to most one return find_package_components - def _get_component_requires(self, dep_name, dep_findname, comp): + def _get_component_requires(self, pkg_name, pkg_findname, comp): comp_requires_findnames = [] for require in comp.requires: - if "::" in require: - comp_require_dep_name = require[:require.find("::")] - if comp_require_dep_name not in self.deps_build_info.deps: + if COMPONENT_SCOPE in require: + comp_require_pkg_name = require[:require.find("::")] + if comp_require_pkg_name not in self.deps_build_info.deps: raise ConanException("Component '%s' not found: '%s' is not a package " - "requirement" % (require, comp_require_dep_name)) - comp_require_dep_findname = self.deps_build_info[comp_require_dep_name].get_name( - "cmake_find_package") + "requirement" % (require, comp_require_pkg_name)) + comp_require_pkg = self.deps_build_info[comp_require_pkg_name] + comp_require_pkg_findname = self._get_name(comp_require_pkg) comp_require_comp_name = require[require.find("::") + 2:] if comp_require_comp_name in self.deps_build_info.deps: - comp_require_comp_findname = comp_require_dep_findname - elif comp_require_comp_name in self.deps_build_info[comp_require_dep_name].components: - comp_require_comp_findname = self.deps_build_info[comp_require_dep_name].components[comp_require_comp_name].get_name("cmake_find_package") + comp_require_comp_findname = comp_require_pkg_findname + elif comp_require_comp_name in self.deps_build_info[comp_require_pkg_name].components: + comp_require_comp = comp_require_pkg.components[comp_require_comp_name] + comp_require_comp_findname = self._get_name(comp_require_comp) else: raise ConanException("Component '%s' not found in '%s' package requirement" - % (require, comp_require_dep_name)) - comp_requires_findnames.append("{}::{}".format(comp_require_dep_findname, comp_require_comp_findname)) + % (require, comp_require_pkg_name)) else: - comp_require_dep_findname = dep_findname - comp_require_findname = self.deps_build_info[dep_name].components[require].get_name( - "cmake_find_package") - comp_requires_findnames.append( - "{}::{}".format(comp_require_dep_findname, comp_require_findname)) + comp_require_pkg_findname = pkg_findname + comp_require_comp = self.deps_build_info[pkg_name].components[require] + comp_require_comp_findname = self._get_name(comp_require_comp) + f = "{}::{}".format(comp_require_pkg_findname, comp_require_comp_findname) + comp_requires_findnames.append(f) return ";".join(comp_requires_findnames) - def _find_for_dep(self, dep_name, cpp_info): - if not cpp_info.components: - dep_findname = cpp_info.get_name("cmake_find_package") + def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): + pkg_version = cpp_info.version + pkg_public_deps = [self._get_name(self.deps_build_info[public_dep]) for public_dep in + cpp_info.public_deps] + if cpp_info.components: + pkg_components = ";".join(["{p}::{c}".format(p=pkg_findname, c=comp_findname) for + comp_findname, _ in self._get_components(pkg_name, + pkg_findname, + cpp_info)]) + pkg_dependencies = ";".join(["{n}::{n}".format(n=dep) for dep in pkg_public_deps]) + return self.find_components_tpl.render( + pkg_name=pkg_findname, + pkg_version=pkg_version, + pkg_components=pkg_components, + pkg_dependencies=pkg_dependencies, + pkg_public_deps=pkg_public_deps, + components=self._get_components(pkg_name, pkg_findname, cpp_info)) + else: # The common macros macros_and_functions = "\n".join([ CMakeFindPackageCommonMacros.conan_message, @@ -276,12 +310,10 @@ def _find_for_dep(self, dep_name, 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 - public_deps_names = [self.deps_build_info[dep].get_name("cmake_find_package") for dep in - dep_cpp_info.public_deps] - deps_names = ";".join(["{n}::{n}".format(n=n) for n in public_deps_names]) + deps_names = ";".join(["{n}::{n}".format(n=n) for n in pkg_public_deps]) deps = DepsCppCmake(dep_cpp_info) - find_libraries_block = target_template.format(name=dep_findname, deps=deps, + find_libraries_block = target_template.format(name=pkg_findname, deps=deps, build_type_suffix="", deps_names=deps_names) @@ -294,17 +326,7 @@ def _find_for_dep(self, dep_name, cpp_info): find_dependencies_block = ''.join(" " + line if line.strip() else line for line in f.splitlines(True)) - tmp = self.find_template.format(name=dep_findname, version=dep_cpp_info.version, - find_libraries_block=find_libraries_block, - find_dependencies_block=find_dependencies_block, - macros_and_functions=macros_and_functions) - return tmp - else: - pkg_name = dep_name - pkg_findname = cpp_info.get_name("cmake_find_package") - return self.find_components_tpl.render( - pkg_name=pkg_findname, - pkg_version=cpp_info.version, - pkg_public_deps=[self.deps_build_info[public_dep].get_name("cmake_find_package") for - public_dep in cpp_info.public_deps], - components=self._get_components(pkg_name, pkg_findname, cpp_info)) + return self.find_template.format(name=pkg_findname, version=pkg_version, + find_libraries_block=find_libraries_block, + find_dependencies_block=find_dependencies_block, + macros_and_functions=macros_and_functions) From ee3f99b9903ae202032e21bb13b526b4e543c6ec Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 27 May 2020 17:36:25 +0200 Subject: [PATCH 03/35] Add components to cmake_find_package generator (jinja2) --- .../generators/cmake_components_test.py | 432 ++++++++++++++++++ 1 file changed, 432 insertions(+) create mode 100644 conans/test/functional/generators/cmake_components_test.py diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py new file mode 100644 index 00000000000..83fab499cec --- /dev/null +++ b/conans/test/functional/generators/cmake_components_test.py @@ -0,0 +1,432 @@ +import textwrap +import unittest + +from conans.test.utils.tools import TestClient + + +class CMakeGeneratorsWithComponentsTest(unittest.TestCase): + + def _test(self, conanfile_greetings=None, cmakelists_greetings=None, conanfile_world=None, + cmakelists_world=None, test_package_cmakelists=None): + client = TestClient() + _conanfile_greetings = textwrap.dedent(""" + from conans import ConanFile, CMake + + class GreetingsConan(ConanFile): + name = "greetings" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + exports_sources = "src/*" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.components["hello"].libs = ["hello"] + self.cpp_info.components["bye"].libs = ["bye"] + """) + hello_h = textwrap.dedent(""" + #pragma once + + void hello(std::string noun); + """) + hello_cpp = textwrap.dedent(""" + #include + #include "hello.h"# We need to add our requirements too + + void hello(std::string noun) { + std::cout << "Hello " << noun << "!" << std::endl; + } + """) + bye_h = textwrap.dedent(""" + #pragma once + + void bye(std::string noun); + """) + bye_cpp = textwrap.dedent(""" + #include + #include "bye.h" + + void bye(std::string noun) { + std::cout << "Bye " << noun << "!" << std::endl; + } + """) + _cmakelists_greetings = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(greetings CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + + add_library(hello hello.cpp) + add_library(bye bye.cpp) + """) + client.save({"conanfile.py": conanfile_greetings or _conanfile_greetings, + "src/CMakeLists.txt": cmakelists_greetings or _cmakelists_greetings, + "src/hello.h": hello_h, + "src/hello.cpp": hello_cpp, + "src/bye.h": bye_h, + "src/bye.cpp": bye_cpp}) + client.run("create .") + + _conanfile_world = textwrap.dedent(""" + from conans import ConanFile, CMake, tools + + class WorldConan(ConanFile): + name = "world" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake_find_package" + exports_sources = "src/*" + requires = "greetings/0.0.1" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.components["helloworld"].requires = ["greetings::greetings"] + self.cpp_info.components["helloworld"].libs = ["helloworld"] + self.cpp_info.components["worldall"].requires = ["greetings::greetings", "helloworld"] + self.cpp_info.components["worldall"].libs = ["worldall"] + """) + helloworld_h = textwrap.dedent(""" + #pragma once + + void helloWorld(); + """) + helloworld_cpp = textwrap.dedent(""" + #include + #include "hello.h" + #include "helloworld.h" + + void helloWorld() { + hello("World"); + } + """) + worldall_h = textwrap.dedent(""" + #pragma once + + void worldAll(); + """) + worldall_cpp = textwrap.dedent(""" + #include + #include "bye.h" + #include "helloworld.h" + #include "worldall.h" + + void worldAll() { + helloWorld(); + bye("World"); + } + """) + _cmakelists_world = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(world CXX) + + find_package(greetings COMPONENTS hello) + + add_library(helloworld helloworld.cpp) + target_link_libraries(helloworld greetings::greetings) + + find_package(greetings COMPONENTS bye) + + add_library(worldall worldall.cpp) + target_link_libraries(worldall helloworld greetings::greetings) + """) + test_package_conanfile = textwrap.dedent(""" + import os + from conans import ConanFile, CMake + + class GreetingsTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake_find_package" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + os.chdir("bin") + self.run(".%sexample" % os.sep) + self.run(".%sexample2" % os.sep) + """) + test_package_example_cpp = textwrap.dedent(""" + #include + #include "worldall.h" + + int main() { + worldAll(); + } + """) + _test_package_cmakelists = textwrap.dedent(""" + cmake_minimum_required(VERSION 2.8.12) + project(PackageTest CXX) + + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + + find_package(world) + + add_executable(example example.cpp) + target_link_libraries(example world::worldall) + + add_executable(example2 example.cpp) + target_link_libraries(example2 world::world) + """) + client.save({"conanfile.py": conanfile_world or _conanfile_world, + "src/CMakeLists.txt": cmakelists_world or _cmakelists_world, + "src/helloworld.h": helloworld_h, + "src/helloworld.cpp": helloworld_cpp, + "src/worldall.h": worldall_h, + "src/worldall.cpp": worldall_cpp, + "test_package/conanfile.py": test_package_conanfile, + "test_package/CMakeLists.txt": test_package_cmakelists or _test_package_cmakelists, + "test_package/example.cpp": test_package_example_cpp}) + client.run("create .") + return client.out + + def component_depends_on_full_package_test(self): + out = self._test() + self.assertIn("Hello World!", out) + self.assertIn("Bye World!", out) + + def find_package_general_test(self): + conanfile_greetings = textwrap.dedent(""" + from conans import ConanFile, CMake + + class GreetingsConan(ConanFile): + name = "greetings" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + exports_sources = "src/*" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.names["cmake_find_package"] = "Greetings" + self.cpp_info.components["hello"].names["cmake_find_package"] = "Hello" + self.cpp_info.components["hello"].libs = ["hello"] + self.cpp_info.components["bye"].names["cmake_find_package"] = "Bye" + self.cpp_info.components["bye"].libs = ["bye"] + """) + + conanfile_world = textwrap.dedent(""" + from conans import ConanFile, CMake + + class WorldConan(ConanFile): + name = "world" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake_find_package" + exports_sources = "src/*" + requires = "greetings/0.0.1" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.names["cmake_find_package"] = "World" + self.cpp_info.components["helloworld"].names["cmake_find_package"] = "Helloworld" + self.cpp_info.components["helloworld"].requires = ["greetings::hello"] + self.cpp_info.components["helloworld"].libs = ["helloworld"] + self.cpp_info.components["worldall"].names["cmake_find_package"] = "Worldall" + self.cpp_info.components["worldall"].requires = ["greetings::bye", "helloworld"] + self.cpp_info.components["worldall"].libs = ["worldall"] + """) + cmakelists2 = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(world CXX) + + find_package(Greetings) + + add_library(Helloworld helloworld.cpp) + target_link_libraries(Helloworld Greetings::Hello) + + add_library(Worldall worldall.cpp) + target_link_libraries(Worldall Helloworld Greetings::Bye) + """) + test_package_cmakelists = textwrap.dedent(""" + cmake_minimum_required(VERSION 2.8.12) + project(PackageTest CXX) + + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + + find_package(world) + + add_executable(example example.cpp) + target_link_libraries(example World::Worldall) + + add_executable(example2 example.cpp) + target_link_libraries(example2 World::World) + """) + out = self._test(conanfile_greetings=conanfile_greetings, + conanfile_world=conanfile_world, cmakelists_world=cmakelists2, + test_package_cmakelists=test_package_cmakelists) + self.assertIn("Hello World!", out) + self.assertIn("Bye World!", out) + + def find_package_components_test(self): + conanfile2 = textwrap.dedent(""" + from conans import ConanFile, CMake, tools + + class WorldConan(ConanFile): + name = "world" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake_find_package" + exports_sources = "src/*" + requires = "greetings/0.0.1" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.components["helloworld"].requires = ["greetings::hello"] + self.cpp_info.components["helloworld"].libs = ["helloworld"] + self.cpp_info.components["worldall"].requires = ["greetings::bye", "helloworld"] + self.cpp_info.components["worldall"].libs = ["worldall"] + """) + cmakelists2 = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(world CXX) + + find_package(greetings COMPONENTS hello) + + add_library(helloworld helloworld.cpp) + target_link_libraries(helloworld greetings::hello) + + find_package(greetings COMPONENTS bye) + + add_library(worldall worldall.cpp) + target_link_libraries(worldall helloworld greetings::bye) + """) + out = self._test(conanfile_world=conanfile2, cmakelists_world=cmakelists2) + self.assertIn("Hello World!", out) + self.assertIn("Bye World!", out) + + def recipe_with_components_requiring_recipe_without_components_test(self): + conanfile1 = textwrap.dedent(""" + from conans import ConanFile, CMake + + class GreetingsConan(ConanFile): + name = "greetings" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + exports_sources = "src/*" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.libs = ["hello", "bye"] + """) + out = self._test(conanfile_greetings=conanfile1) + self.assertIn("Hello World!", out) + self.assertIn("Bye World!", out) + + def component_not_found_test(self): + conanfile = textwrap.dedent(""" + from conans import ConanFile, CMake + + class GreetingsConan(ConanFile): + name = "greetings" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + + def package_info(self): + self.cpp_info.components["hello"].libs = ["hello"] + """) + client = TestClient() + client.save({"conanfile.py": conanfile}) + client.run("create conanfile.py") + + conanfile = textwrap.dedent(""" + from conans import ConanFile, CMake + + class WorldConan(ConanFile): + name = "world" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + requires = "greetings/0.0.1" + + def package_info(self): + self.cpp_info.components["helloworld"].requires = ["greetings::non-existent"] + self.cpp_info.components["helloworld"].libs = ["helloworld"] + """) + client.save({"conanfile.py": conanfile}) + client.run("create conanfile.py") + client.run("install world/0.0.1@ -g cmake_find_package", assert_error=True) + self.assertIn("ERROR: Component 'greetings::non-existent' not found in 'greetings' " + "package requirement", client.out) From 2612927ad834bdf412304c4376ca71cc98a37b6a Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 27 May 2020 17:50:33 +0200 Subject: [PATCH 04/35] fix --- conans/client/generators/cmake_find_package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 76742575e46..4fc0e01efc5 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -321,7 +321,7 @@ def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): find_dependencies_block = "" if dep_cpp_info.public_deps: # Here we are generating FindXXX, so find_modules=True - f = find_transitive_dependencies(public_deps_names, find_modules=True) + f = find_transitive_dependencies(pkg_public_deps, find_modules=True) # proper indentation find_dependencies_block = ''.join(" " + line if line.strip() else line for line in f.splitlines(True)) From b936911cd52e53ae2c3762a0bc413b0f7c35168f Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 27 May 2020 17:51:18 +0200 Subject: [PATCH 05/35] tag tests as slow --- conans/test/functional/generators/cmake_components_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 83fab499cec..713c12108fc 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -1,9 +1,12 @@ import textwrap import unittest +from nose.plugins.attrib import attr + from conans.test.utils.tools import TestClient +@attr('slow') class CMakeGeneratorsWithComponentsTest(unittest.TestCase): def _test(self, conanfile_greetings=None, cmakelists_greetings=None, conanfile_world=None, From 25f241ff0f55bd9adc88621818824aa8d457db1e Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 27 May 2020 18:51:56 +0200 Subject: [PATCH 06/35] try fix --- .../functional/generators/cmake_components_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 713c12108fc..465fd47e75c 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -46,7 +46,7 @@ def package_info(self): """) hello_cpp = textwrap.dedent(""" #include - #include "hello.h"# We need to add our requirements too + #include "hello.h" void hello(std::string noun) { std::cout << "Hello " << noun << "!" << std::endl; @@ -84,7 +84,7 @@ def package_info(self): client.run("create .") _conanfile_world = textwrap.dedent(""" - from conans import ConanFile, CMake, tools + from conans import ConanFile, CMake class WorldConan(ConanFile): name = "world" @@ -184,7 +184,7 @@ def test(self): } """) _test_package_cmakelists = textwrap.dedent(""" - cmake_minimum_required(VERSION 2.8.12) + cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) @@ -296,7 +296,7 @@ def package_info(self): target_link_libraries(Worldall Helloworld Greetings::Bye) """) test_package_cmakelists = textwrap.dedent(""" - cmake_minimum_required(VERSION 2.8.12) + cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) @@ -321,7 +321,7 @@ def package_info(self): def find_package_components_test(self): conanfile2 = textwrap.dedent(""" - from conans import ConanFile, CMake, tools + from conans import ConanFile, CMake class WorldConan(ConanFile): name = "world" From 5652556fe55e18e578a71338f7f653265f24b3ca Mon Sep 17 00:00:00 2001 From: danimtb Date: Thu, 28 May 2020 11:30:31 +0200 Subject: [PATCH 07/35] try and print --- .../client/generators/cmake_find_package.py | 21 ++++++++++++------- .../generators/cmake_components_test.py | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 4fc0e01efc5..1aaa75e7bc6 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -174,8 +174,10 @@ class CMakeFindPackageGenerator(Generator): set({{ comp_name }}_FRAMEWORKS_FOUND "") # Will be filled later conan_find_apple_frameworks({{ comp_name }}_FRAMEWORKS_FOUND "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORK_DIRS{% raw %}}{% endraw %}") - set({{ comp_name }}_LINK_LIBS "${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_SYSTEM_LIBS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS_FOUND{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_DEPENDENCIES{% raw %}}{% endraw %}") - + conan_message(STATUS "COMPONENT LIB TARGETS: ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %}") + conan_message(STATUS "COMPONENT_DEPENDENCIES: ${% raw %}{{% endraw %}{{ comp_name }}_DEPENDENCIES{% raw %}}{% endraw %}") + set({{ comp_name }}_LINK_LIBS ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_SYSTEM_LIBS{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS_FOUND{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_DEPENDENCIES{% raw %}}{% endraw %}) + conan_message(STATUS "COMPONENT LINK LIBS: ${% raw %}{{% endraw %}{{ comp_name }}_LINK_LIBS{% raw %}}{% endraw %}") set(CMAKE_MODULE_PATH {{ comp.build_paths }} ${CMAKE_MODULE_PATH}) set(CMAKE_PREFIX_PATH {{ comp.build_paths }} ${CMAKE_PREFIX_PATH}) @@ -203,7 +205,8 @@ class CMakeFindPackageGenerator(Generator): set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_LINK_DIRECTORIES "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}") set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_LINK_LIBRARIES - "${% raw %}{{% endraw %}{{ comp_name }}_LINK_LIBS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}") + ${% raw %}{{% endraw %}{{ comp_name }}_LINK_LIBS{% raw %}}{% endraw %} + ${% raw %}{{% endraw %}{{ comp_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}) set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_DEFINITIONS ${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_DEFINITIONS{% raw %}}{% endraw %}) set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_OPTIONS @@ -218,8 +221,11 @@ class CMakeFindPackageGenerator(Generator): if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") if(NOT TARGET {{ pkg_name }}::{{ pkg_name }}) add_library({{ pkg_name }}::{{ pkg_name }} INTERFACE IMPORTED) + conan_message("${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %}") + conan_message(STATUS "PKG DEPENDENCIES: ${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}") set_property(TARGET {{ pkg_name }}::{{ pkg_name }} PROPERTY INTERFACE_LINK_LIBRARIES - "${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}") + ${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %} + ${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}) endif() endif() @@ -247,6 +253,7 @@ def _get_components(self, pkg_name, pkg_findname, cpp_info): comp_findname = self._get_name(cpp_info.components[comp_name]) deps_cpp_cmake = DepsCppCmake(comp) deps_cpp_cmake.public_deps = self._get_component_requires(pkg_name, pkg_findname, comp) + print(comp_name, "public_deps: ", deps_cpp_cmake.public_deps) find_package_components.append((comp_findname, deps_cpp_cmake)) find_package_components.reverse() # From the less dependent to most one return find_package_components @@ -276,18 +283,18 @@ def _get_component_requires(self, pkg_name, pkg_findname, comp): comp_require_comp_findname = self._get_name(comp_require_comp) f = "{}::{}".format(comp_require_pkg_findname, comp_require_comp_findname) comp_requires_findnames.append(f) - return ";".join(comp_requires_findnames) + return " ".join(comp_requires_findnames) def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): pkg_version = cpp_info.version pkg_public_deps = [self._get_name(self.deps_build_info[public_dep]) for public_dep in cpp_info.public_deps] if cpp_info.components: - pkg_components = ";".join(["{p}::{c}".format(p=pkg_findname, c=comp_findname) for + pkg_components = " ".join(["{p}::{c}".format(p=pkg_findname, c=comp_findname) for comp_findname, _ in self._get_components(pkg_name, pkg_findname, cpp_info)]) - pkg_dependencies = ";".join(["{n}::{n}".format(n=dep) for dep in pkg_public_deps]) + pkg_dependencies = " ".join(["{n}::{n}".format(n=dep) for dep in pkg_public_deps]) return self.find_components_tpl.render( pkg_name=pkg_findname, pkg_version=pkg_version, diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 465fd47e75c..f0d0772b730 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -211,6 +211,7 @@ def test(self): "test_package/CMakeLists.txt": test_package_cmakelists or _test_package_cmakelists, "test_package/example.cpp": test_package_example_cpp}) client.run("create .") + print(client.out) return client.out def component_depends_on_full_package_test(self): From 96a0a44ed8283af4f0613a37b799e4a7a8087f7f Mon Sep 17 00:00:00 2001 From: danimtb Date: Thu, 28 May 2020 11:52:41 +0200 Subject: [PATCH 08/35] Fix find --- conans/test/functional/generators/cmake_components_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index f0d0772b730..77bdbf48ca1 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -284,7 +284,7 @@ def package_info(self): self.cpp_info.components["worldall"].requires = ["greetings::bye", "helloworld"] self.cpp_info.components["worldall"].libs = ["worldall"] """) - cmakelists2 = textwrap.dedent(""" + cmakelists_world = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(world CXX) @@ -306,7 +306,7 @@ def package_info(self): set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - find_package(world) + find_package(World) add_executable(example example.cpp) target_link_libraries(example World::Worldall) @@ -315,7 +315,7 @@ def package_info(self): target_link_libraries(example2 World::World) """) out = self._test(conanfile_greetings=conanfile_greetings, - conanfile_world=conanfile_world, cmakelists_world=cmakelists2, + conanfile_world=conanfile_world, cmakelists_world=cmakelists_world, test_package_cmakelists=test_package_cmakelists) self.assertIn("Hello World!", out) self.assertIn("Bye World!", out) From 169f93c094f867768f6ecf4a7e47a119ea7ec9df Mon Sep 17 00:00:00 2001 From: danimtb Date: Thu, 28 May 2020 13:01:33 +0200 Subject: [PATCH 09/35] try without example2 --- .../functional/generators/cmake_components_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 77bdbf48ca1..afe2b4e2ca4 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -173,7 +173,7 @@ def build(self): def test(self): os.chdir("bin") self.run(".%sexample" % os.sep) - self.run(".%sexample2" % os.sep) + # self.run(".%sexample2" % os.sep) """) test_package_example_cpp = textwrap.dedent(""" #include @@ -198,8 +198,8 @@ def test(self): add_executable(example example.cpp) target_link_libraries(example world::worldall) - add_executable(example2 example.cpp) - target_link_libraries(example2 world::world) + # add_executable(example2 example.cpp) + # target_link_libraries(example2 world::world) """) client.save({"conanfile.py": conanfile_world or _conanfile_world, "src/CMakeLists.txt": cmakelists_world or _cmakelists_world, @@ -311,8 +311,8 @@ def package_info(self): add_executable(example example.cpp) target_link_libraries(example World::Worldall) - add_executable(example2 example.cpp) - target_link_libraries(example2 World::World) + # add_executable(example2 example.cpp) + # target_link_libraries(example2 World::World) """) out = self._test(conanfile_greetings=conanfile_greetings, conanfile_world=conanfile_world, cmakelists_world=cmakelists_world, From 53b01b19e6309ba0ead87d96313b45fd2bd3f412 Mon Sep 17 00:00:00 2001 From: danimtb Date: Thu, 28 May 2020 15:54:06 +0200 Subject: [PATCH 10/35] add link flags, use set_target_property(), fix test --- .../client/generators/cmake_find_package.py | 29 ++++++++++--------- .../generators/cmake_components_test.py | 10 +++++-- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 1aaa75e7bc6..1d50d08a8f7 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -92,7 +92,7 @@ class CMakeFindPackageGenerator(Generator): endif() conan_message(STATUS "Found: ${CONAN_FOUND_LIBRARY}") else() - conan_message(STATUS "Library ${_LIBRARY_NAME} NOT FOUND!!") + message(FATAL_ERROR "Component library ${_LIBRARY_NAME} not found in paths: ${libdir}") endif() unset(CONAN_FOUND_LIBRARY CACHE) endforeach() @@ -140,6 +140,11 @@ class CMakeFindPackageGenerator(Generator): set({{ comp_name }}_FRAMEWORKS {{ comp.frameworks }}) set({{ comp_name }}_BUILD_MODULES_PATHS {{ comp.build_modules_paths }}) set({{ comp_name }}_DEPENDENCIES {{ comp.public_deps }}) + set({{ comp_name }}_LINKER_FLAGS_LIST + $<$,SHARED_LIBRARY>:{{ comp.sharedlinkflags_list }}> + $<$,MODULE_LIBRARY>:{{ comp.sharedlinkflags_list }}> + $<$,EXECUTABLE>:{{ comp.exelinkflags_list }}> + ) {%- endfor %} @@ -202,15 +207,14 @@ class CMakeFindPackageGenerator(Generator): add_library({{ pkg_name }}::{{ comp_name }} INTERFACE IMPORTED) set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${% raw %}{{% endraw %}{{ comp_name }}_INCLUDE_DIRS{% raw %}}{% endraw %}") - set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_LINK_DIRECTORIES - "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}") - set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_LINK_LIBRARIES - ${% raw %}{{% endraw %}{{ comp_name }}_LINK_LIBS{% raw %}}{% endraw %} - ${% raw %}{{% endraw %}{{ comp_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}) - set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_DEFINITIONS - ${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_DEFINITIONS{% raw %}}{% endraw %}) - set_property(TARGET {{ pkg_name }}::{{ comp_name }} PROPERTY INTERFACE_COMPILE_OPTIONS - "${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_OPTIONS_LIST{% raw %}}{% endraw %}") + set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_LINK_DIRECTORIES + "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}") + set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_LINK_LIBRARIES + "${% raw %}{{% endraw %}{{ comp_name }}_LINK_LIBS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}") + set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_COMPILE_DEFINITIONS + "${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_DEFINITIONS{% raw %}}{% endraw %}") + set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_COMPILE_OPTIONS + "${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_OPTIONS_LIST{% raw %}}{% endraw %}") endif() endif() @@ -223,9 +227,8 @@ class CMakeFindPackageGenerator(Generator): add_library({{ pkg_name }}::{{ pkg_name }} INTERFACE IMPORTED) conan_message("${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %}") conan_message(STATUS "PKG DEPENDENCIES: ${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}") - set_property(TARGET {{ pkg_name }}::{{ pkg_name }} PROPERTY INTERFACE_LINK_LIBRARIES - ${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %} - ${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}) + set_target_properties({{ pkg_name }}::{{ pkg_name }} PROPERTIES INTERFACE_LINK_LIBRARIES + "${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}") endif() endif() diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index afe2b4e2ca4..b93351bcfb9 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -194,6 +194,9 @@ def test(self): set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) find_package(world) + + get_target_property(tmp world::worldall INTERFACE_LINK_LIBRARIES) + message("world::worldall target libs: ${tmp}") add_executable(example example.cpp) target_link_libraries(example world::worldall) @@ -279,10 +282,10 @@ def package_info(self): self.cpp_info.names["cmake_find_package"] = "World" self.cpp_info.components["helloworld"].names["cmake_find_package"] = "Helloworld" self.cpp_info.components["helloworld"].requires = ["greetings::hello"] - self.cpp_info.components["helloworld"].libs = ["helloworld"] + self.cpp_info.components["helloworld"].libs = ["Helloworld"] self.cpp_info.components["worldall"].names["cmake_find_package"] = "Worldall" self.cpp_info.components["worldall"].requires = ["greetings::bye", "helloworld"] - self.cpp_info.components["worldall"].libs = ["worldall"] + self.cpp_info.components["worldall"].libs = ["Worldall"] """) cmakelists_world = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) @@ -308,6 +311,9 @@ def package_info(self): find_package(World) + get_target_property(tmp World::Worldall INTERFACE_LINK_LIBRARIES) + message("World::Worldall target libs: ${tmp}") + add_executable(example example.cpp) target_link_libraries(example World::Worldall) From cc0b8cebd60c0ab07941dc1f3d34c602fe7c0ff1 Mon Sep 17 00:00:00 2001 From: danimtb Date: Thu, 28 May 2020 17:35:15 +0200 Subject: [PATCH 11/35] push test --- .../client/generators/cmake_find_package.py | 4 + .../generators/cmake_components_test.py | 135 +++++++++++++++++- 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 1d50d08a8f7..235988f3fe7 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -175,6 +175,10 @@ class CMakeFindPackageGenerator(Generator): set({{ comp_name }}_LIB_TARGETS "") # Will be filled later, if CMake 3 conan_component_library_targets({{ comp_name }}_LIB_TARGETS "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_LIBS{% raw %}}{% endraw %}") conan_message(STATUS "Components Library targets2: ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %}") + # foreach(_LIB ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %}) + # set_target_properties(${_LIB} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + # "${% raw %}{{% endraw %}{{ comp_name }}_INCLUDE_DIRS{% raw %}}{% endraw %}") + # endforeach() set({{ comp_name }}_FRAMEWORKS_FOUND "") # Will be filled later conan_find_apple_frameworks({{ comp_name }}_FRAMEWORKS_FOUND "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORK_DIRS{% raw %}}{% endraw %}") diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index b93351bcfb9..2232172389a 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -161,7 +161,7 @@ def package_info(self): import os from conans import ConanFile, CMake - class GreetingsTestConan(ConanFile): + class WorldTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "cmake_find_package" @@ -217,6 +217,133 @@ def test(self): print(client.out) return client.out + def basic_test(self): + client = TestClient() + conanfile_greetings = textwrap.dedent(""" + from conans import ConanFile, CMake + + class GreetingsConan(ConanFile): + name = "greetings" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + exports_sources = "src/*" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.components["hello"].libs = ["hello"] + self.cpp_info.components["bye"].libs = ["bye"] + """) + hello_h = textwrap.dedent(""" + #pragma once + + void hello(std::string noun); + """) + hello_cpp = textwrap.dedent(""" + #include + #include "hello.h" + + void hello(std::string noun) { + std::cout << "Hello " << noun << "!" << std::endl; + } + """) + bye_h = textwrap.dedent(""" + #pragma once + + void bye(std::string noun); + """) + bye_cpp = textwrap.dedent(""" + #include + #include "bye.h" + + void bye(std::string noun) { + std::cout << "Bye " << noun << "!" << std::endl; + } + """) + cmakelists_greetings = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(greetings CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + + add_library(hello hello.cpp) + add_library(bye bye.cpp) + """) + test_package_greetings_conanfile = textwrap.dedent(""" + import os + from conans import ConanFile, CMake + + class GreetingsTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake_find_package" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + os.chdir("bin") + self.run(".%sexample" % os.sep) + """) + test_package_greetings_cpp = textwrap.dedent(""" + #include + #include "hello.h" + #include "bye.h" + + int main() { + hello("Moon"); + bye("Moon"); + } + """) + test_package_greetings_cmakelists = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(PackageTest CXX) + + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + + find_package(greetings) + + get_target_property(tmp greetings::greetings INTERFACE_LINK_LIBRARIES) + message("greetings::greetings target libs: ${tmp}") + get_target_property(tmp greetings::hello INTERFACE_LINK_LIBRARIES) + message("greetings::Hello target libs: ${tmp}") + get_target_property(tmp greetings::bye INTERFACE_LINK_LIBRARIES) + message("greetings::bye target libs: ${tmp}") + get_target_property(tmp bye IMPORTED_LOCATION) + message("bye imported location: ${tmp}") + + add_executable(example example.cpp) + target_link_libraries(example greetings::greetings) + """) + client.save({"conanfile.py": conanfile_greetings, + "src/CMakeLists.txt": cmakelists_greetings, + "src/hello.h": hello_h, + "src/hello.cpp": hello_cpp, + "src/bye.h": bye_h, + "src/bye.cpp": bye_cpp, + "test_package/conanfile.py": test_package_greetings_conanfile, + "test_package/example.cpp": test_package_greetings_cpp, + "test_package/CMakeLists.txt": test_package_greetings_cmakelists}) + client.run("create .") + def component_depends_on_full_package_test(self): out = self._test() self.assertIn("Hello World!", out) @@ -313,6 +440,12 @@ def package_info(self): get_target_property(tmp World::Worldall INTERFACE_LINK_LIBRARIES) message("World::Worldall target libs: ${tmp}") + get_target_property(tmp World::Helloworld INTERFACE_LINK_LIBRARIES) + message("World::Helloworld target libs: ${tmp}") + get_target_property(tmp Greetings::Bye INTERFACE_LINK_LIBRARIES) + message("Greetings::Bye target libs: ${tmp}") + get_target_property(tmp Greetings::Hello INTERFACE_LINK_LIBRARIES) + message("Greetings::Hello target libs: ${tmp}") add_executable(example example.cpp) target_link_libraries(example World::Worldall) From 734bb58bd56b0412f9c23d874a268648f840d907 Mon Sep 17 00:00:00 2001 From: danimtb Date: Thu, 28 May 2020 18:40:32 +0200 Subject: [PATCH 12/35] Use conan_basic_setup() --- .../generators/cmake_components_test.py | 239 +++++++++--------- 1 file changed, 121 insertions(+), 118 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 2232172389a..ac4bcec970c 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -90,7 +90,7 @@ class WorldConan(ConanFile): name = "world" version = "0.0.1" settings = "os", "compiler", "build_type", "arch" - generators = "cmake_find_package" + generators = "cmake_find_package", "cmake" exports_sources = "src/*" requires = "greetings/0.0.1" @@ -112,7 +112,7 @@ def package_info(self): self.cpp_info.components["helloworld"].libs = ["helloworld"] self.cpp_info.components["worldall"].requires = ["greetings::greetings", "helloworld"] self.cpp_info.components["worldall"].libs = ["worldall"] - """) + """) helloworld_h = textwrap.dedent(""" #pragma once @@ -147,6 +147,9 @@ def package_info(self): cmake_minimum_required(VERSION 3.0) project(world CXX) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + find_package(greetings COMPONENTS hello) add_library(helloworld helloworld.cpp) @@ -156,14 +159,14 @@ def package_info(self): add_library(worldall worldall.cpp) target_link_libraries(worldall helloworld greetings::greetings) - """) + """) test_package_conanfile = textwrap.dedent(""" import os from conans import ConanFile, CMake class WorldTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" - generators = "cmake_find_package" + generators = "cmake", "cmake_find_package" def build(self): cmake = CMake(self) @@ -174,7 +177,7 @@ def test(self): os.chdir("bin") self.run(".%sexample" % os.sep) # self.run(".%sexample2" % os.sep) - """) + """) test_package_example_cpp = textwrap.dedent(""" #include #include "worldall.h" @@ -187,11 +190,8 @@ def test(self): cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() find_package(world) @@ -220,119 +220,116 @@ def test(self): def basic_test(self): client = TestClient() conanfile_greetings = textwrap.dedent(""" - from conans import ConanFile, CMake - - class GreetingsConan(ConanFile): - name = "greetings" - version = "0.0.1" - settings = "os", "compiler", "build_type", "arch" - generators = "cmake" - exports_sources = "src/*" - - def build(self): - cmake = CMake(self) - cmake.configure(source_folder="src") - cmake.build() - - def package(self): - self.copy("*.h", dst="include", src="src") - self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) - self.copy("*.a", dst="lib", keep_path=False) - - def package_info(self): - self.cpp_info.components["hello"].libs = ["hello"] - self.cpp_info.components["bye"].libs = ["bye"] - """) + from conans import ConanFile, CMake + + class GreetingsConan(ConanFile): + name = "greetings" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + exports_sources = "src/*" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.components["hello"].libs = ["hello"] + self.cpp_info.components["bye"].libs = ["bye"] + """) hello_h = textwrap.dedent(""" - #pragma once + #pragma once - void hello(std::string noun); - """) + void hello(std::string noun); + """) hello_cpp = textwrap.dedent(""" - #include - #include "hello.h" + #include + #include "hello.h" - void hello(std::string noun) { - std::cout << "Hello " << noun << "!" << std::endl; - } - """) + void hello(std::string noun) { + std::cout << "Hello " << noun << "!" << std::endl; + } + """) bye_h = textwrap.dedent(""" - #pragma once + #pragma once - void bye(std::string noun); - """) + void bye(std::string noun); + """) bye_cpp = textwrap.dedent(""" - #include - #include "bye.h" + #include + #include "bye.h" - void bye(std::string noun) { - std::cout << "Bye " << noun << "!" << std::endl; - } - """) + void bye(std::string noun) { + std::cout << "Bye " << noun << "!" << std::endl; + } + """) cmakelists_greetings = textwrap.dedent(""" - cmake_minimum_required(VERSION 3.0) - project(greetings CXX) - - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_basic_setup() + cmake_minimum_required(VERSION 3.0) + project(greetings CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() - add_library(hello hello.cpp) - add_library(bye bye.cpp) - """) + add_library(hello hello.cpp) + add_library(bye bye.cpp) + """) test_package_greetings_conanfile = textwrap.dedent(""" - import os - from conans import ConanFile, CMake - - class GreetingsTestConan(ConanFile): - settings = "os", "compiler", "build_type", "arch" - generators = "cmake_find_package" - - def build(self): - cmake = CMake(self) - cmake.configure() - cmake.build() - - def test(self): - os.chdir("bin") - self.run(".%sexample" % os.sep) - """) + import os + from conans import ConanFile, CMake + + class GreetingsTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake", "cmake_find_package" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + os.chdir("bin") + self.run(".%sexample" % os.sep) + """) test_package_greetings_cpp = textwrap.dedent(""" - #include - #include "hello.h" - #include "bye.h" - - int main() { - hello("Moon"); - bye("Moon"); - } - """) + #include + #include "hello.h" + #include "bye.h" + + int main() { + hello("Moon"); + bye("Moon"); + } + """) test_package_greetings_cmakelists = textwrap.dedent(""" - cmake_minimum_required(VERSION 3.0) - project(PackageTest CXX) - - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - - find_package(greetings) - - get_target_property(tmp greetings::greetings INTERFACE_LINK_LIBRARIES) - message("greetings::greetings target libs: ${tmp}") - get_target_property(tmp greetings::hello INTERFACE_LINK_LIBRARIES) - message("greetings::Hello target libs: ${tmp}") - get_target_property(tmp greetings::bye INTERFACE_LINK_LIBRARIES) - message("greetings::bye target libs: ${tmp}") - get_target_property(tmp bye IMPORTED_LOCATION) - message("bye imported location: ${tmp}") - - add_executable(example example.cpp) - target_link_libraries(example greetings::greetings) - """) + cmake_minimum_required(VERSION 3.0) + project(PackageTest CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + + find_package(greetings) + + get_target_property(tmp greetings::greetings INTERFACE_LINK_LIBRARIES) + message("greetings::greetings target libs: ${tmp}") + get_target_property(tmp greetings::hello INTERFACE_LINK_LIBRARIES) + message("greetings::Hello target libs: ${tmp}") + get_target_property(tmp greetings::bye INTERFACE_LINK_LIBRARIES) + message("greetings::bye target libs: ${tmp}") + get_target_property(tmp bye IMPORTED_LOCATION) + message("bye imported location: ${tmp}") + + add_executable(example example.cpp) + target_link_libraries(example greetings::greetings) + """) client.save({"conanfile.py": conanfile_greetings, "src/CMakeLists.txt": cmakelists_greetings, "src/hello.h": hello_h, @@ -343,6 +340,8 @@ def test(self): "test_package/example.cpp": test_package_greetings_cpp, "test_package/CMakeLists.txt": test_package_greetings_cmakelists}) client.run("create .") + self.assertIn("Hello Moon!", client.out) + self.assertIn("Bye Moon!", client.out) def component_depends_on_full_package_test(self): out = self._test() @@ -388,7 +387,7 @@ class WorldConan(ConanFile): name = "world" version = "0.0.1" settings = "os", "compiler", "build_type", "arch" - generators = "cmake_find_package" + generators = "cmake", "cmake_find_package" exports_sources = "src/*" requires = "greetings/0.0.1" @@ -417,6 +416,9 @@ def package_info(self): cmakelists_world = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(world CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() find_package(Greetings) @@ -430,11 +432,9 @@ def package_info(self): cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_set_std() + conan_output_dirs_setup() find_package(World) @@ -448,7 +448,7 @@ def package_info(self): message("Greetings::Hello target libs: ${tmp}") add_executable(example example.cpp) - target_link_libraries(example World::Worldall) + target_link_libraries(example World::Worldall Greetings::Bye Greetings::Hello) # add_executable(example2 example.cpp) # target_link_libraries(example2 World::World) @@ -467,7 +467,7 @@ class WorldConan(ConanFile): name = "world" version = "0.0.1" settings = "os", "compiler", "build_type", "arch" - generators = "cmake_find_package" + generators = "cmake", "cmake_find_package" exports_sources = "src/*" requires = "greetings/0.0.1" @@ -493,6 +493,9 @@ def package_info(self): cmakelists2 = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(world CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() find_package(greetings COMPONENTS hello) From ef52ab50ff0795369d5a4e7e9741fe75e29d495f Mon Sep 17 00:00:00 2001 From: danimtb Date: Fri, 29 May 2020 13:14:24 +0200 Subject: [PATCH 13/35] Fix test --- conans/test/functional/generators/cmake_components_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index ac4bcec970c..bab5058de6b 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -433,8 +433,7 @@ def package_info(self): project(PackageTest CXX) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_set_std() - conan_output_dirs_setup() + conan_basic_setup() find_package(World) @@ -448,7 +447,7 @@ def package_info(self): message("Greetings::Hello target libs: ${tmp}") add_executable(example example.cpp) - target_link_libraries(example World::Worldall Greetings::Bye Greetings::Hello) + target_link_libraries(example World::Worldall) # add_executable(example2 example.cpp) # target_link_libraries(example2 World::World) From f75fc5742d5f84908a1b243813ca6a2bce3fd059 Mon Sep 17 00:00:00 2001 From: danimtb Date: Fri, 29 May 2020 13:45:06 +0200 Subject: [PATCH 14/35] Fix ALL tests FINALLY! --- conans/client/generators/cmake_find_package.py | 1 - .../functional/generators/cmake_components_test.py | 10 ++++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 235988f3fe7..456b1ac9fe6 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -90,7 +90,6 @@ class CMakeFindPackageGenerator(Generator): endif() list(APPEND _out_libraries_target ${_LIB_NAME}) endif() - conan_message(STATUS "Found: ${CONAN_FOUND_LIBRARY}") else() message(FATAL_ERROR "Component library ${_LIBRARY_NAME} not found in paths: ${libdir}") endif() diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index bab5058de6b..7f2ab85eca3 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -110,7 +110,7 @@ def package(self): def package_info(self): self.cpp_info.components["helloworld"].requires = ["greetings::greetings"] self.cpp_info.components["helloworld"].libs = ["helloworld"] - self.cpp_info.components["worldall"].requires = ["greetings::greetings", "helloworld"] + self.cpp_info.components["worldall"].requires = ["helloworld", "greetings::greetings"] self.cpp_info.components["worldall"].libs = ["worldall"] """) helloworld_h = textwrap.dedent(""" @@ -194,9 +194,15 @@ def test(self): conan_basic_setup() find_package(world) - + + get_target_property(tmp world::world INTERFACE_LINK_LIBRARIES) + message("world::world target libs: ${tmp}") get_target_property(tmp world::worldall INTERFACE_LINK_LIBRARIES) message("world::worldall target libs: ${tmp}") + get_target_property(tmp world::helloworld INTERFACE_LINK_LIBRARIES) + message("world::helloworld target libs: ${tmp}") + get_target_property(tmp greetings::greetings INTERFACE_LINK_LIBRARIES) + message("greetings::greetings target libs: ${tmp}") add_executable(example example.cpp) target_link_libraries(example world::worldall) From fcb26e618f2f964bb811552cc3b995eb8c01d17e Mon Sep 17 00:00:00 2001 From: danimtb Date: Fri, 29 May 2020 14:17:38 +0200 Subject: [PATCH 15/35] add example2, fix tests, add reverse and format messages --- .../client/generators/cmake_find_package.py | 35 +++++++------------ .../generators/cmake_components_test.py | 31 ++++------------ 2 files changed, 19 insertions(+), 47 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 456b1ac9fe6..61637475e55 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -66,7 +66,7 @@ class CMakeFindPackageGenerator(Generator): if(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND) list(APPEND ${FRAMEWORKS_FOUND} ${CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND}) else() - message(FATAL_ERROR "Framework library ${_FRAMEWORK} not found in paths: ${FRAMEWORKS_DIRS}") + message(FATAL_ERROR "Conan:Framework library ${_FRAMEWORK} not found in paths: ${FRAMEWORKS_DIRS}") endif() endforeach() endif() @@ -77,7 +77,7 @@ class CMakeFindPackageGenerator(Generator): find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${libdir} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) if(CONAN_FOUND_LIBRARY) - conan_message(STATUS "Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}") + conan_message(STATUS "Conan: Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}") if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") # Create a micro-target for each lib/a found set(_LIB_NAME ${_LIBRARY_NAME}) @@ -86,17 +86,17 @@ class CMakeFindPackageGenerator(Generator): add_library(${_LIB_NAME} UNKNOWN IMPORTED) set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION ${CONAN_FOUND_LIBRARY}) else() - conan_message(STATUS "Skipping already existing target: ${_LIB_NAME}") + conan_message(STATUS "Conan: Skipping already existing target: ${_LIB_NAME}") endif() list(APPEND _out_libraries_target ${_LIB_NAME}) endif() else() - message(FATAL_ERROR "Component library ${_LIBRARY_NAME} not found in paths: ${libdir}") + conan_message(FATAL_ERROR "Conan: Component library ${_LIBRARY_NAME} not found in paths: ${libdir}") endif() unset(CONAN_FOUND_LIBRARY CACHE) endforeach() - conan_message(STATUS "Components Library targets: ${_out_libraries_target}") + conan_message(STATUS "Conan: Component library targets: ${_out_libraries_target}") set(${out_libraries_target} ${_out_libraries_target} PARENT_SCOPE) endfunction() {% endraw %} @@ -158,7 +158,7 @@ class CMakeFindPackageGenerator(Generator): if(NOT {{ public_dep }}_FOUND) find_dependency({{ public_dep }} REQUIRED) else() - message(STATUS "Dependency {{ public_dep }} already found") + conan_message(STATUS "Conan: Dependency {{ public_dep }} already found") endif() {%- endfor %} @@ -173,19 +173,11 @@ class CMakeFindPackageGenerator(Generator): set({{ comp_name }}_LIB_TARGETS "") # Will be filled later, if CMake 3 conan_component_library_targets({{ comp_name }}_LIB_TARGETS "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_LIBS{% raw %}}{% endraw %}") - conan_message(STATUS "Components Library targets2: ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %}") - # foreach(_LIB ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %}) - # set_target_properties(${_LIB} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - # "${% raw %}{{% endraw %}{{ comp_name }}_INCLUDE_DIRS{% raw %}}{% endraw %}") - # endforeach() set({{ comp_name }}_FRAMEWORKS_FOUND "") # Will be filled later conan_find_apple_frameworks({{ comp_name }}_FRAMEWORKS_FOUND "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORK_DIRS{% raw %}}{% endraw %}") - conan_message(STATUS "COMPONENT LIB TARGETS: ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %}") - conan_message(STATUS "COMPONENT_DEPENDENCIES: ${% raw %}{{% endraw %}{{ comp_name }}_DEPENDENCIES{% raw %}}{% endraw %}") set({{ comp_name }}_LINK_LIBS ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_SYSTEM_LIBS{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS_FOUND{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_DEPENDENCIES{% raw %}}{% endraw %}) - conan_message(STATUS "COMPONENT LINK LIBS: ${% raw %}{{% endraw %}{{ comp_name }}_LINK_LIBS{% raw %}}{% endraw %}") set(CMAKE_MODULE_PATH {{ comp.build_paths }} ${CMAKE_MODULE_PATH}) set(CMAKE_PREFIX_PATH {{ comp.build_paths }} ${CMAKE_PREFIX_PATH}) @@ -228,8 +220,6 @@ class CMakeFindPackageGenerator(Generator): if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") if(NOT TARGET {{ pkg_name }}::{{ pkg_name }}) add_library({{ pkg_name }}::{{ pkg_name }} INTERFACE IMPORTED) - conan_message("${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %}") - conan_message(STATUS "PKG DEPENDENCIES: ${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}") set_target_properties({{ pkg_name }}::{{ pkg_name }} PROPERTIES INTERFACE_LINK_LIBRARIES "${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}") endif() @@ -253,28 +243,28 @@ def content(self): ret["Find%s.cmake" % pkg_findname] = self._find_for_dep(pkg_name, pkg_findname, cpp_info) return ret - def _get_components(self, pkg_name, pkg_findname, cpp_info): + def _get_components(self, pkg_name, pkg_findname, cpp_info, reverse=True): find_package_components = [] for comp_name, comp in cpp_info._get_sorted_components().items(): comp_findname = self._get_name(cpp_info.components[comp_name]) deps_cpp_cmake = DepsCppCmake(comp) deps_cpp_cmake.public_deps = self._get_component_requires(pkg_name, pkg_findname, comp) - print(comp_name, "public_deps: ", deps_cpp_cmake.public_deps) find_package_components.append((comp_findname, deps_cpp_cmake)) - find_package_components.reverse() # From the less dependent to most one + if reverse: + find_package_components.reverse() # From the less dependent to most one return find_package_components def _get_component_requires(self, pkg_name, pkg_findname, comp): comp_requires_findnames = [] for require in comp.requires: if COMPONENT_SCOPE in require: - comp_require_pkg_name = require[:require.find("::")] + comp_require_pkg_name = require[:require.find(COMPONENT_SCOPE)] if comp_require_pkg_name not in self.deps_build_info.deps: raise ConanException("Component '%s' not found: '%s' is not a package " "requirement" % (require, comp_require_pkg_name)) comp_require_pkg = self.deps_build_info[comp_require_pkg_name] comp_require_pkg_findname = self._get_name(comp_require_pkg) - comp_require_comp_name = require[require.find("::") + 2:] + comp_require_comp_name = require[require.find(COMPONENT_SCOPE)+len(COMPONENT_SCOPE):] if comp_require_comp_name in self.deps_build_info.deps: comp_require_comp_findname = comp_require_pkg_findname elif comp_require_comp_name in self.deps_build_info[comp_require_pkg_name].components: @@ -299,7 +289,8 @@ def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): pkg_components = " ".join(["{p}::{c}".format(p=pkg_findname, c=comp_findname) for comp_findname, _ in self._get_components(pkg_name, pkg_findname, - cpp_info)]) + cpp_info, + reverse=False)]) pkg_dependencies = " ".join(["{n}::{n}".format(n=dep) for dep in pkg_public_deps]) return self.find_components_tpl.render( pkg_name=pkg_findname, diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 7f2ab85eca3..aedd6936c41 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -176,7 +176,7 @@ def build(self): def test(self): os.chdir("bin") self.run(".%sexample" % os.sep) - # self.run(".%sexample2" % os.sep) + self.run(".%sexample2" % os.sep) """) test_package_example_cpp = textwrap.dedent(""" #include @@ -195,20 +195,11 @@ def test(self): find_package(world) - get_target_property(tmp world::world INTERFACE_LINK_LIBRARIES) - message("world::world target libs: ${tmp}") - get_target_property(tmp world::worldall INTERFACE_LINK_LIBRARIES) - message("world::worldall target libs: ${tmp}") - get_target_property(tmp world::helloworld INTERFACE_LINK_LIBRARIES) - message("world::helloworld target libs: ${tmp}") - get_target_property(tmp greetings::greetings INTERFACE_LINK_LIBRARIES) - message("greetings::greetings target libs: ${tmp}") - add_executable(example example.cpp) target_link_libraries(example world::worldall) - # add_executable(example2 example.cpp) - # target_link_libraries(example2 world::world) + add_executable(example2 example.cpp) + target_link_libraries(example2 world::world) """) client.save({"conanfile.py": conanfile_world or _conanfile_world, "src/CMakeLists.txt": cmakelists_world or _cmakelists_world, @@ -220,7 +211,6 @@ def test(self): "test_package/CMakeLists.txt": test_package_cmakelists or _test_package_cmakelists, "test_package/example.cpp": test_package_example_cpp}) client.run("create .") - print(client.out) return client.out def basic_test(self): @@ -324,15 +314,6 @@ def test(self): find_package(greetings) - get_target_property(tmp greetings::greetings INTERFACE_LINK_LIBRARIES) - message("greetings::greetings target libs: ${tmp}") - get_target_property(tmp greetings::hello INTERFACE_LINK_LIBRARIES) - message("greetings::Hello target libs: ${tmp}") - get_target_property(tmp greetings::bye INTERFACE_LINK_LIBRARIES) - message("greetings::bye target libs: ${tmp}") - get_target_property(tmp bye IMPORTED_LOCATION) - message("bye imported location: ${tmp}") - add_executable(example example.cpp) target_link_libraries(example greetings::greetings) """) @@ -455,8 +436,8 @@ def package_info(self): add_executable(example example.cpp) target_link_libraries(example World::Worldall) - # add_executable(example2 example.cpp) - # target_link_libraries(example2 World::World) + add_executable(example2 example.cpp) + target_link_libraries(example2 World::World) """) out = self._test(conanfile_greetings=conanfile_greetings, conanfile_world=conanfile_world, cmakelists_world=cmakelists_world, @@ -492,7 +473,7 @@ def package(self): def package_info(self): self.cpp_info.components["helloworld"].requires = ["greetings::hello"] self.cpp_info.components["helloworld"].libs = ["helloworld"] - self.cpp_info.components["worldall"].requires = ["greetings::bye", "helloworld"] + self.cpp_info.components["worldall"].requires = ["helloworld", "greetings::bye"] self.cpp_info.components["worldall"].libs = ["worldall"] """) cmakelists2 = textwrap.dedent(""" From 88afd4571f7d8ba762b204378e9dc667f24e2646 Mon Sep 17 00:00:00 2001 From: danimtb Date: Fri, 29 May 2020 14:58:46 +0200 Subject: [PATCH 16/35] add sorted_components() to base generator class --- conans/client/generators/cmake_find_package.py | 2 +- conans/model/conan_generator.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 61637475e55..2dead03510d 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -245,7 +245,7 @@ def content(self): def _get_components(self, pkg_name, pkg_findname, cpp_info, reverse=True): find_package_components = [] - for comp_name, comp in cpp_info._get_sorted_components().items(): + for comp_name, comp in self.sorted_components(cpp_info).items(): comp_findname = self._get_name(cpp_info.components[comp_name]) deps_cpp_cmake = DepsCppCmake(comp) deps_cpp_cmake.public_deps = self._get_component_requires(pkg_name, pkg_findname, comp) diff --git a/conans/model/conan_generator.py b/conans/model/conan_generator.py index 603dc381183..fc205ad014b 100644 --- a/conans/model/conan_generator.py +++ b/conans/model/conan_generator.py @@ -41,3 +41,6 @@ def content(self): @abstractproperty def filename(self): raise NotImplementedError() + + def sorted_components(self, cpp_info): + return cpp_info._get_sorted_components() From c3f8af32dd8b5500b3c1162465bd803365eb0626 Mon Sep 17 00:00:00 2001 From: danimtb Date: Fri, 29 May 2020 15:16:03 +0200 Subject: [PATCH 17/35] fix includes and remove messages --- .../generators/cmake_components_test.py | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index aedd6936c41..981b7a48a81 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -46,6 +46,8 @@ def package_info(self): """) hello_cpp = textwrap.dedent(""" #include + #include + #include "hello.h" void hello(std::string noun) { @@ -59,6 +61,8 @@ def package_info(self): """) bye_cpp = textwrap.dedent(""" #include + #include + #include "bye.h" void bye(std::string noun) { @@ -119,8 +123,9 @@ def package_info(self): void helloWorld(); """) helloworld_cpp = textwrap.dedent(""" - #include + #include #include "hello.h" + #include "helloworld.h" void helloWorld() { @@ -133,9 +138,10 @@ def package_info(self): void worldAll(); """) worldall_cpp = textwrap.dedent(""" - #include + #include #include "bye.h" #include "helloworld.h" + #include "worldall.h" void worldAll() { @@ -179,7 +185,6 @@ def test(self): self.run(".%sexample2" % os.sep) """) test_package_example_cpp = textwrap.dedent(""" - #include #include "worldall.h" int main() { @@ -249,6 +254,8 @@ def package_info(self): """) hello_cpp = textwrap.dedent(""" #include + #include + #include "hello.h" void hello(std::string noun) { @@ -262,6 +269,8 @@ def package_info(self): """) bye_cpp = textwrap.dedent(""" #include + #include + #include "bye.h" void bye(std::string noun) { @@ -296,7 +305,8 @@ def test(self): self.run(".%sexample" % os.sep) """) test_package_greetings_cpp = textwrap.dedent(""" - #include + #include + #include "hello.h" #include "bye.h" @@ -424,15 +434,6 @@ def package_info(self): find_package(World) - get_target_property(tmp World::Worldall INTERFACE_LINK_LIBRARIES) - message("World::Worldall target libs: ${tmp}") - get_target_property(tmp World::Helloworld INTERFACE_LINK_LIBRARIES) - message("World::Helloworld target libs: ${tmp}") - get_target_property(tmp Greetings::Bye INTERFACE_LINK_LIBRARIES) - message("Greetings::Bye target libs: ${tmp}") - get_target_property(tmp Greetings::Hello INTERFACE_LINK_LIBRARIES) - message("Greetings::Hello target libs: ${tmp}") - add_executable(example example.cpp) target_link_libraries(example World::Worldall) From bb65e78d87cb85f7266f8170e5029b776af4dc0e Mon Sep 17 00:00:00 2001 From: danimtb Date: Fri, 29 May 2020 15:45:09 +0200 Subject: [PATCH 18/35] Change jinja syntax --- .../client/generators/cmake_find_package.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 2dead03510d..4a2c2267d36 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -172,17 +172,17 @@ class CMakeFindPackageGenerator(Generator): ########## COMPONENT {{ comp_name }} FIND LIBRARIES & FRAMEWORKS / DYNAMIC VARS ############# set({{ comp_name }}_LIB_TARGETS "") # Will be filled later, if CMake 3 - conan_component_library_targets({{ comp_name }}_LIB_TARGETS "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_LIBS{% raw %}}{% endraw %}") + conan_component_library_targets({{ comp_name }}_LIB_TARGETS "{{ '${'+comp_name+'_LIB_DIRS}' }}" "{{ '${'+comp_name+'_LIBS}' }}") set({{ comp_name }}_FRAMEWORKS_FOUND "") # Will be filled later - conan_find_apple_frameworks({{ comp_name }}_FRAMEWORKS_FOUND "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS{% raw %}}{% endraw %}" "${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORK_DIRS{% raw %}}{% endraw %}") + conan_find_apple_frameworks({{ comp_name }}_FRAMEWORKS_FOUND "{{ '${'+comp_name+'_FRAMEWORKS}' }}" "{{ '${'+comp_name+'_FRAMEWORK_DIRS}' }}") - set({{ comp_name }}_LINK_LIBS ${% raw %}{{% endraw %}{{ comp_name }}_LIB_TARGETS{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_SYSTEM_LIBS{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_FRAMEWORKS_FOUND{% raw %}}{% endraw %} ${% raw %}{{% endraw %}{{ comp_name }}_DEPENDENCIES{% raw %}}{% endraw %}) + set({{ comp_name }}_LINK_LIBS {{ '${'+comp_name+'_LIB_TARGETS}' }} {{ '${'+comp_name+'_SYSTEM_LIBS}' }} {{ '${'+comp_name+'_FRAMEWORKS_FOUND}' }} {{ '${'+comp_name+'_DEPENDENCIES}' }}) set(CMAKE_MODULE_PATH {{ comp.build_paths }} ${CMAKE_MODULE_PATH}) set(CMAKE_PREFIX_PATH {{ comp.build_paths }} ${CMAKE_PREFIX_PATH}) - foreach(_BUILD_MODULE_PATH ${% raw %}{{% endraw %}{{ comp_name }}_BUILD_MODULES_PATHS{% raw %}}{% endraw %}) + foreach(_BUILD_MODULE_PATH {{ '${'+comp_name+'_BUILD_MODULES_PATHS}' }}) include(${_BUILD_MODULE_PATH}) endforeach() @@ -201,15 +201,15 @@ class CMakeFindPackageGenerator(Generator): if(NOT TARGET {{ pkg_name }}::{{ comp_name }}) add_library({{ pkg_name }}::{{ comp_name }} INTERFACE IMPORTED) set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${% raw %}{{% endraw %}{{ comp_name }}_INCLUDE_DIRS{% raw %}}{% endraw %}") + "{{ '${'+comp_name+'_INCLUDE_DIRS}' }}") set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_LINK_DIRECTORIES - "${% raw %}{{% endraw %}{{ comp_name }}_LIB_DIRS{% raw %}}{% endraw %}") + "{{ '${'+comp_name+'_LIB_DIRS}' }}") set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_LINK_LIBRARIES - "${% raw %}{{% endraw %}{{ comp_name }}_LINK_LIBS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ comp_name }}_LINKER_FLAGS_LIST{% raw %}}{% endraw %}") + "{{ '${'+comp_name+'_LINK_LIBS}' }};{{ '${'+comp_name+'_LINKER_FLAGS_LIST}' }}") set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_COMPILE_DEFINITIONS - "${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_DEFINITIONS{% raw %}}{% endraw %}") + "{{ '${'+comp_name+'_COMPILE_DEFINITIONS}' }}") set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_COMPILE_OPTIONS - "${% raw %}{{% endraw %}{{ comp_name }}_COMPILE_OPTIONS_LIST{% raw %}}{% endraw %}") + "{{ '${'+comp_name+'_COMPILE_OPTIONS_LIST}' }}") endif() endif() @@ -221,7 +221,7 @@ class CMakeFindPackageGenerator(Generator): if(NOT TARGET {{ pkg_name }}::{{ pkg_name }}) add_library({{ pkg_name }}::{{ pkg_name }} INTERFACE IMPORTED) set_target_properties({{ pkg_name }}::{{ pkg_name }} PROPERTIES INTERFACE_LINK_LIBRARIES - "${% raw %}{{% endraw %}{{ pkg_name }}_COMPONENTS{% raw %}}{% endraw %};${% raw %}{{% endraw %}{{ pkg_name }}_DEPENDENCIES{% raw %}}{% endraw %}") + "{{ '${'+pkg_name+'_COMPONENTS}' }};{{ '${'+pkg_name+'_DEPENDENCIES}' }}") endif() endif() From d897f79d836e578a6602e4889c589f4a578c713e Mon Sep 17 00:00:00 2001 From: danimtb Date: Mon, 1 Jun 2020 10:08:38 +0200 Subject: [PATCH 19/35] test component with same name as global --- .../generators/cmake_components_test.py | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 981b7a48a81..43e069f411a 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -563,3 +563,105 @@ def package_info(self): client.run("install world/0.0.1@ -g cmake_find_package", assert_error=True) self.assertIn("ERROR: Component 'greetings::non-existent' not found in 'greetings' " "package requirement", client.out) + + def same_names_test(self): + client = TestClient() + conanfile_greetings = textwrap.dedent(""" + from conans import ConanFile, CMake + + class HelloConan(ConanFile): + name = "hello" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + exports_sources = "src/*" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.components["global"].name = "hello" + self.cpp_info.components["global"].libs = ["hello"] + """) + hello_h = textwrap.dedent(""" + #pragma once + + void hello(std::string noun); + """) + hello_cpp = textwrap.dedent(""" + #include + #include + + #include "hello.h" + + void hello(std::string noun) { + std::cout << "Hello " << noun << "!" << std::endl; + } + """) + cmakelists_greetings = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(greetings CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + + add_library(hello hello.cpp) + """) + test_package_greetings_conanfile = textwrap.dedent(""" + import os + from conans import ConanFile, CMake + + class HelloTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake", "cmake_find_package" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + os.chdir("bin") + self.run(".%sexample" % os.sep) + """) + test_package_greetings_cpp = textwrap.dedent(""" + #include + + #include "hello.h" + + int main() { + hello("Moon"); + } + """) + test_package_greetings_cmakelists = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(PackageTest CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + + find_package(hello) + + add_executable(example example.cpp) + target_link_libraries(example hello::hello) + """) + client.save({"conanfile.py": conanfile_greetings, + "src/CMakeLists.txt": cmakelists_greetings, + "src/hello.h": hello_h, + "src/hello.cpp": hello_cpp, + "test_package/conanfile.py": test_package_greetings_conanfile, + "test_package/example.cpp": test_package_greetings_cpp, + "test_package/CMakeLists.txt": test_package_greetings_cmakelists}) + client.run("create .") + print(client.out) + self.assertIn("Hello Moon!", client.out) From 6fa9ad1afa244a76e65adfae0558243e86690b44 Mon Sep 17 00:00:00 2001 From: danimtb Date: Mon, 1 Jun 2020 10:15:55 +0200 Subject: [PATCH 20/35] remove dependencies from global target --- conans/client/generators/cmake_find_package.py | 5 +---- conans/test/functional/generators/cmake_components_test.py | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 4a2c2267d36..129a73d5d4d 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -119,7 +119,6 @@ class CMakeFindPackageGenerator(Generator): ############################################################################################# set({{ pkg_name }}_COMPONENTS {{ pkg_components }}) - set({{ pkg_name }}_DEPENDENCIES {{ pkg_dependencies }}) {%- for comp_name, comp in components %} @@ -221,7 +220,7 @@ class CMakeFindPackageGenerator(Generator): if(NOT TARGET {{ pkg_name }}::{{ pkg_name }}) add_library({{ pkg_name }}::{{ pkg_name }} INTERFACE IMPORTED) set_target_properties({{ pkg_name }}::{{ pkg_name }} PROPERTIES INTERFACE_LINK_LIBRARIES - "{{ '${'+pkg_name+'_COMPONENTS}' }};{{ '${'+pkg_name+'_DEPENDENCIES}' }}") + "{{ '${'+pkg_name+'_COMPONENTS}' }}") endif() endif() @@ -291,12 +290,10 @@ def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): pkg_findname, cpp_info, reverse=False)]) - pkg_dependencies = " ".join(["{n}::{n}".format(n=dep) for dep in pkg_public_deps]) return self.find_components_tpl.render( pkg_name=pkg_findname, pkg_version=pkg_version, pkg_components=pkg_components, - pkg_dependencies=pkg_dependencies, pkg_public_deps=pkg_public_deps, components=self._get_components(pkg_name, pkg_findname, cpp_info)) else: diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 43e069f411a..880a392d7e7 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -663,5 +663,4 @@ def test(self): "test_package/example.cpp": test_package_greetings_cpp, "test_package/CMakeLists.txt": test_package_greetings_cmakelists}) client.run("create .") - print(client.out) self.assertIn("Hello Moon!", client.out) From b7d4580c3356b8f93ca8437ac881192da4b507a1 Mon Sep 17 00:00:00 2001 From: danimtb Date: Mon, 1 Jun 2020 10:42:10 +0200 Subject: [PATCH 21/35] Link mini-targets to other components --- .../client/generators/cmake_find_package.py | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 129a73d5d4d..1355c520201 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -72,7 +72,7 @@ class CMakeFindPackageGenerator(Generator): endif() endmacro() - function(conan_component_library_targets out_libraries_target libdir libraries) + function(conan_component_library_targets out_libraries_target libdir libraries dependencies system_libs frameworks) foreach(_LIBRARY_NAME ${libraries}) find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${libdir} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) @@ -96,6 +96,12 @@ class CMakeFindPackageGenerator(Generator): unset(CONAN_FOUND_LIBRARY CACHE) endforeach() + # Add all dependencies to all targets + string(REPLACE " " ";" deps_list "${dependencies}") + foreach(_out_library_target ${_out_libraries_target}) + set_property(TARGET ${_out_library_target} PROPERTY INTERFACE_LINK_LIBRARIES "${deps_list};${system_libs};${frameworks}") + endforeach() + conan_message(STATUS "Conan: Component library targets: ${_out_libraries_target}") set(${out_libraries_target} ${_out_libraries_target} PARENT_SCOPE) endfunction() @@ -170,13 +176,18 @@ class CMakeFindPackageGenerator(Generator): ########## COMPONENT {{ comp_name }} FIND LIBRARIES & FRAMEWORKS / DYNAMIC VARS ############# - set({{ comp_name }}_LIB_TARGETS "") # Will be filled later, if CMake 3 - conan_component_library_targets({{ comp_name }}_LIB_TARGETS "{{ '${'+comp_name+'_LIB_DIRS}' }}" "{{ '${'+comp_name+'_LIBS}' }}") - - set({{ comp_name }}_FRAMEWORKS_FOUND "") # Will be filled later + set({{ comp_name }}_FRAMEWORKS_FOUND "") conan_find_apple_frameworks({{ comp_name }}_FRAMEWORKS_FOUND "{{ '${'+comp_name+'_FRAMEWORKS}' }}" "{{ '${'+comp_name+'_FRAMEWORK_DIRS}' }}") - set({{ comp_name }}_LINK_LIBS {{ '${'+comp_name+'_LIB_TARGETS}' }} {{ '${'+comp_name+'_SYSTEM_LIBS}' }} {{ '${'+comp_name+'_FRAMEWORKS_FOUND}' }} {{ '${'+comp_name+'_DEPENDENCIES}' }}) + set({{ comp_name }}_LIB_TARGETS "") + conan_component_library_targets({{ comp_name }}_LIB_TARGETS + "{{ '${'+comp_name+'_LIB_DIRS}' }}" + "{{ '${'+comp_name+'_LIBS}' }}" + "{{ '${'+comp_name+'_DEPENDENCIES}' }}" + "{{ '${'+comp_name+'_SYSTEM_LIBS}' }}" + "{{ '${'+comp_name+'_FRAMEWORKS_FOUND}' }}") + + set({{ comp_name }}_LINK_LIBS {{ '${'+comp_name+'_LIB_TARGETS}' }} {{ '${'+comp_name+'_DEPENDENCIES}' }}) set(CMAKE_MODULE_PATH {{ comp.build_paths }} ${CMAKE_MODULE_PATH}) set(CMAKE_PREFIX_PATH {{ comp.build_paths }} ${CMAKE_PREFIX_PATH}) From a0f2b487f8bbc55a256c7875b36321c05fde2b26 Mon Sep 17 00:00:00 2001 From: danimtb Date: Mon, 1 Jun 2020 13:13:29 +0200 Subject: [PATCH 22/35] Update test with slightly different behavior --- .../generators/cmake_components_test.py | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 880a392d7e7..b4dbc8fafd1 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -112,7 +112,7 @@ def package(self): self.copy("*.a", dst="lib", keep_path=False) def package_info(self): - self.cpp_info.components["helloworld"].requires = ["greetings::greetings"] + self.cpp_info.components["helloworld"].requires = ["greetings::hello"] self.cpp_info.components["helloworld"].libs = ["helloworld"] self.cpp_info.components["worldall"].requires = ["helloworld", "greetings::greetings"] self.cpp_info.components["worldall"].libs = ["worldall"] @@ -159,7 +159,7 @@ def package_info(self): find_package(greetings COMPONENTS hello) add_library(helloworld helloworld.cpp) - target_link_libraries(helloworld greetings::greetings) + target_link_libraries(helloworld greetings::hello) find_package(greetings COMPONENTS bye) @@ -525,7 +525,55 @@ def package(self): def package_info(self): self.cpp_info.libs = ["hello", "bye"] """) - out = self._test(conanfile_greetings=conanfile1) + conanfile2 = textwrap.dedent(""" + from conans import ConanFile, CMake + + class WorldConan(ConanFile): + name = "world" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake", "cmake_find_package" + exports_sources = "src/*" + requires = "greetings/0.0.1" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.dll", dst="bin", keep_path=False) + self.copy("*.dylib*", dst="lib", keep_path=False) + self.copy("*.so", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.components["helloworld"].requires = ["greetings::greetings"] + self.cpp_info.components["helloworld"].libs = ["helloworld"] + self.cpp_info.components["worldall"].requires = ["helloworld", "greetings::greetings"] + self.cpp_info.components["worldall"].libs = ["worldall"] + """) + cmakelists2 = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(world CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + + find_package(greetings COMPONENTS hello) + + add_library(helloworld helloworld.cpp) + target_link_libraries(helloworld greetings::greetings) + + find_package(greetings COMPONENTS bye) + + add_library(worldall worldall.cpp) + target_link_libraries(worldall helloworld greetings::greetings) + """) + out = self._test(conanfile_greetings=conanfile1, conanfile_world=conanfile2, + cmakelists_world=cmakelists2) self.assertIn("Hello World!", out) self.assertIn("Bye World!", out) From 593041cdbe661ca851cf4aeddacfef4d416852e5 Mon Sep 17 00:00:00 2001 From: danimtb Date: Mon, 1 Jun 2020 16:01:38 +0200 Subject: [PATCH 23/35] use name and classmethod --- conans/client/generators/cmake_find_package.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 1355c520201..1379d7e1d06 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -12,7 +12,7 @@ class CMakeFindPackageGenerator(Generator): - generator_name = "cmake_find_package" + name = "cmake_find_package" find_template = textwrap.dedent(""" {macros_and_functions} @@ -241,9 +241,10 @@ class CMakeFindPackageGenerator(Generator): def filename(self): return None - def _get_name(self, obj): + @classmethod + def _get_name(cls, obj): get_name = getattr(obj, "get_name") - return get_name(self.generator_name) + return get_name(cls.name) @property def content(self): From 2ea386835f029b462f580f1f4ea21874ece4bf5a Mon Sep 17 00:00:00 2001 From: danimtb Date: Mon, 1 Jun 2020 16:10:01 +0200 Subject: [PATCH 24/35] reuse macros --- .../client/generators/cmake_find_package.py | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 1379d7e1d06..85d3c47402f 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -51,27 +51,9 @@ class CMakeFindPackageGenerator(Generator): find_components_tpl = Template(textwrap.dedent("""\ ########## MACROS ########################################################################### ############################################################################################# + {{ conan_message }} + {{ conan_find_apple_frameworks }} {% raw %} - function(conan_message MESSAGE_OUTPUT) - if(NOT CONAN_CMAKE_SILENT_OUTPUT) - message(${ARGV${0}}) - endif() - endfunction() - - macro(conan_find_apple_frameworks FRAMEWORKS_FOUND FRAMEWORKS FRAMEWORKS_DIRS) - if(APPLE) - foreach(_FRAMEWORK ${FRAMEWORKS}) - # https://cmake.org/pipermail/cmake-developers/2017-August/030199.html - find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAME ${_FRAMEWORK} PATHS ${FRAMEWORKS_DIRS}) - if(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND) - list(APPEND ${FRAMEWORKS_FOUND} ${CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND}) - else() - message(FATAL_ERROR "Conan:Framework library ${_FRAMEWORK} not found in paths: ${FRAMEWORKS_DIRS}") - endif() - endforeach() - endif() - endmacro() - function(conan_component_library_targets out_libraries_target libdir libraries dependencies system_libs frameworks) foreach(_LIBRARY_NAME ${libraries}) find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${libdir} @@ -307,7 +289,9 @@ def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): pkg_version=pkg_version, pkg_components=pkg_components, pkg_public_deps=pkg_public_deps, - components=self._get_components(pkg_name, pkg_findname, cpp_info)) + components=self._get_components(pkg_name, pkg_findname, cpp_info), + conan_message=CMakeFindPackageCommonMacros.conan_message, + conan_find_apple_frameworks=CMakeFindPackageCommonMacros.apple_frameworks_macro) else: # The common macros macros_and_functions = "\n".join([ From e41865779bf85e9afe69177780246e98d2265b79 Mon Sep 17 00:00:00 2001 From: danimtb Date: Mon, 1 Jun 2020 16:18:50 +0200 Subject: [PATCH 25/35] use split --- conans/client/generators/cmake_find_package.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 85d3c47402f..4eebaeba151 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -251,13 +251,9 @@ def _get_component_requires(self, pkg_name, pkg_findname, comp): comp_requires_findnames = [] for require in comp.requires: if COMPONENT_SCOPE in require: - comp_require_pkg_name = require[:require.find(COMPONENT_SCOPE)] - if comp_require_pkg_name not in self.deps_build_info.deps: - raise ConanException("Component '%s' not found: '%s' is not a package " - "requirement" % (require, comp_require_pkg_name)) + comp_require_pkg_name, comp_require_comp_name = require.split(COMPONENT_SCOPE) comp_require_pkg = self.deps_build_info[comp_require_pkg_name] comp_require_pkg_findname = self._get_name(comp_require_pkg) - comp_require_comp_name = require[require.find(COMPONENT_SCOPE)+len(COMPONENT_SCOPE):] if comp_require_comp_name in self.deps_build_info.deps: comp_require_comp_findname = comp_require_pkg_findname elif comp_require_comp_name in self.deps_build_info[comp_require_pkg_name].components: From 91f1ab656b14aa5cc90f15a5fd8e19e8a52af42d Mon Sep 17 00:00:00 2001 From: danimtb Date: Mon, 1 Jun 2020 17:30:56 +0200 Subject: [PATCH 26/35] fix with test --- .../client/generators/cmake_find_package.py | 2 +- .../generators/cmake_components_test.py | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 4eebaeba151..e5899f5908e 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -254,7 +254,7 @@ def _get_component_requires(self, pkg_name, pkg_findname, comp): comp_require_pkg_name, comp_require_comp_name = require.split(COMPONENT_SCOPE) comp_require_pkg = self.deps_build_info[comp_require_pkg_name] comp_require_pkg_findname = self._get_name(comp_require_pkg) - if comp_require_comp_name in self.deps_build_info.deps: + if comp_require_comp_name == comp_require_pkg_name: comp_require_comp_findname = comp_require_pkg_findname elif comp_require_comp_name in self.deps_build_info[comp_require_pkg_name].components: comp_require_comp = comp_require_pkg.components[comp_require_comp_name] diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index b4dbc8fafd1..9f64e1d3aec 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -1,8 +1,11 @@ +import os import textwrap import unittest from nose.plugins.attrib import attr +from conans.model.ref import ConanFileReference +from conans.test.utils.genconanfile import GenConanfile from conans.test.utils.tools import TestClient @@ -712,3 +715,22 @@ def test(self): "test_package/CMakeLists.txt": test_package_greetings_cmakelists}) client.run("create .") self.assertIn("Hello Moon!", client.out) + + def component_not_found_same_name_as_pkg_require_test(self): + zlib = GenConanfile("zlib", "0.1").with_generator("cmake_find_package") + mypkg = GenConanfile("mypkg", "0.1").with_generator("cmake_find_package") + final = GenConanfile("final", "0.1").with_generator("cmake_find_package")\ + .with_require(ConanFileReference("zlib", "0.1", None, None))\ + .with_require(ConanFileReference("mypkg", "0.1", None, None))\ + .with_package_info(cpp_info={"components": {"cmp": {"requires": ["mypkg::zlib", + "zlib::zlib"]}}}, + env_info={}) + consumer = GenConanfile("consumer", "0.1").with_generator("cmake_find_package")\ + .with_requirement(ConanFileReference("final", "0.1", None, None)) + client = TestClient() + client.save({"zlib.py": zlib, "mypkg.py": mypkg, "final.py": final, "consumer.py": consumer}) + client.run("create zlib.py") + client.run("create mypkg.py") + client.run("create final.py") + client.run("install consumer.py", assert_error=True) + self.assertIn("Component 'mypkg::zlib' not found in 'mypkg' package requirement", client.out) From 02955c8cf60c25ed7dc191d66531725b7274262b Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 3 Jun 2020 02:09:59 +0200 Subject: [PATCH 27/35] refactor --- .../client/generators/cmake_find_package.py | 15 +- .../generators/cmake_components_test.py | 432 ++++++------------ 2 files changed, 144 insertions(+), 303 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index e5899f5908e..134b1053a9b 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -236,15 +236,14 @@ def content(self): ret["Find%s.cmake" % pkg_findname] = self._find_for_dep(pkg_name, pkg_findname, cpp_info) return ret - def _get_components(self, pkg_name, pkg_findname, cpp_info, reverse=True): + def _get_components(self, pkg_name, pkg_findname, cpp_info): find_package_components = [] for comp_name, comp in self.sorted_components(cpp_info).items(): comp_findname = self._get_name(cpp_info.components[comp_name]) deps_cpp_cmake = DepsCppCmake(comp) deps_cpp_cmake.public_deps = self._get_component_requires(pkg_name, pkg_findname, comp) find_package_components.append((comp_findname, deps_cpp_cmake)) - if reverse: - find_package_components.reverse() # From the less dependent to most one + find_package_components.reverse() # From the less dependent to most one return find_package_components def _get_component_requires(self, pkg_name, pkg_findname, comp): @@ -271,21 +270,21 @@ def _get_component_requires(self, pkg_name, pkg_findname, comp): return " ".join(comp_requires_findnames) def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): + # return the content of the FindXXX.cmake file for the package "pkg_name" pkg_version = cpp_info.version pkg_public_deps = [self._get_name(self.deps_build_info[public_dep]) for public_dep in cpp_info.public_deps] if cpp_info.components: + components = self._get_components(pkg_name, pkg_findname, 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 self._get_components(pkg_name, - pkg_findname, - cpp_info, - reverse=False)]) + comp_findname, _ in reversed(components)]) return self.find_components_tpl.render( pkg_name=pkg_findname, pkg_version=pkg_version, pkg_components=pkg_components, pkg_public_deps=pkg_public_deps, - components=self._get_components(pkg_name, pkg_findname, cpp_info), + components=components, conan_message=CMakeFindPackageCommonMacros.conan_message, conan_find_apple_frameworks=CMakeFindPackageCommonMacros.apple_frameworks_macro) else: diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 9f64e1d3aec..447f81dd5e5 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -1,4 +1,3 @@ -import os import textwrap import unittest @@ -12,10 +11,41 @@ @attr('slow') class CMakeGeneratorsWithComponentsTest(unittest.TestCase): - def _test(self, conanfile_greetings=None, cmakelists_greetings=None, conanfile_world=None, - cmakelists_world=None, test_package_cmakelists=None): - client = TestClient() - _conanfile_greetings = textwrap.dedent(""" + @staticmethod + def _create_greetings(client, custom_names=False, components=True, test=False): + hello_h = textwrap.dedent(""" + #pragma once + void hello(std::string noun); + """) + + hello_cpp = textwrap.dedent(""" + #include + #include + + #include "hello.h" + + void hello(std::string noun) { + std::cout << "Hello " << noun << "!" << std::endl; + } + """) + + bye_h = textwrap.dedent(""" + #pragma once + void bye(std::string noun); + """) + + bye_cpp = textwrap.dedent(""" + #include + #include + + #include "bye.h" + + void bye(std::string noun) { + std::cout << "Bye " << noun << "!" << std::endl; + } + """) + + conanfile_greetings = textwrap.dedent(""" from conans import ConanFile, CMake class GreetingsConan(ConanFile): @@ -33,63 +63,93 @@ def build(self): def package(self): self.copy("*.h", dst="include", src="src") self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) self.copy("*.a", dst="lib", keep_path=False) def package_info(self): - self.cpp_info.components["hello"].libs = ["hello"] - self.cpp_info.components["bye"].libs = ["bye"] - """) - hello_h = textwrap.dedent(""" - #pragma once + %s + """) + if components: + info = textwrap.dedent(""" + self.cpp_info.components["hello"].libs = ["hello"] + self.cpp_info.components["bye"].libs = ["bye"] + """) + if custom_names: + info += textwrap.dedent(""" + self.cpp_info.names["cmake_find_package"] = "Greetings" + self.cpp_info.components["hello"].names["cmake_find_package"] = "Hello" + self.cpp_info.components["bye"].names["cmake_find_package"] = "Bye" + """) + else: + info = textwrap.dedent(""" + self.cpp_info.libs = ["hello", "bye"] + """) + conanfile_greetings = conanfile_greetings % textwrap.indent(info, " ") - void hello(std::string noun); - """) - hello_cpp = textwrap.dedent(""" - #include - #include + cmakelists_greetings = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(greetings CXX) - #include "hello.h" + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() - void hello(std::string noun) { - std::cout << "Hello " << noun << "!" << std::endl; - } + add_library(hello hello.cpp) + add_library(bye bye.cpp) """) - bye_h = textwrap.dedent(""" - #pragma once - void bye(std::string noun); + test_package_greetings_conanfile = textwrap.dedent(""" + import os + from conans import ConanFile, CMake + + class GreetingsTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake", "cmake_find_package" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + os.chdir("bin") + self.run(".%sexample" % os.sep) """) - bye_cpp = textwrap.dedent(""" - #include + test_package_greetings_cpp = textwrap.dedent(""" #include + #include "hello.h" #include "bye.h" - void bye(std::string noun) { - std::cout << "Bye " << noun << "!" << std::endl; + int main() { + hello("Moon"); + bye("Moon"); } """) - _cmakelists_greetings = textwrap.dedent(""" + test_package_greetings_cmakelists = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) - project(greetings CXX) + project(PackageTest CXX) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() - add_library(hello hello.cpp) - add_library(bye bye.cpp) + find_package(greetings) + + add_executable(example example.cpp) + target_link_libraries(example greetings::greetings) """) - client.save({"conanfile.py": conanfile_greetings or _conanfile_greetings, - "src/CMakeLists.txt": cmakelists_greetings or _cmakelists_greetings, + client.save({"conanfile.py": conanfile_greetings, + "src/CMakeLists.txt": cmakelists_greetings, "src/hello.h": hello_h, "src/hello.cpp": hello_cpp, "src/bye.h": bye_h, "src/bye.cpp": bye_cpp}) + if test: + client.save({"test_package/conanfile.py": test_package_greetings_conanfile, + "test_package/example.cpp": test_package_greetings_cpp, + "test_package/CMakeLists.txt": test_package_greetings_cmakelists}) client.run("create .") + @staticmethod + def _create_world(client, conanfile=None, cmakelists=None, test_package_cmakelists=None): _conanfile_world = textwrap.dedent(""" from conans import ConanFile, CMake @@ -109,15 +169,13 @@ def build(self): def package(self): self.copy("*.h", dst="include", src="src") self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) self.copy("*.a", dst="lib", keep_path=False) def package_info(self): self.cpp_info.components["helloworld"].requires = ["greetings::hello"] self.cpp_info.components["helloworld"].libs = ["helloworld"] - self.cpp_info.components["worldall"].requires = ["helloworld", "greetings::greetings"] + self.cpp_info.components["worldall"].requires = ["helloworld", + "greetings::greetings"] self.cpp_info.components["worldall"].libs = ["worldall"] """) helloworld_h = textwrap.dedent(""" @@ -209,8 +267,8 @@ def test(self): add_executable(example2 example.cpp) target_link_libraries(example2 world::world) """) - client.save({"conanfile.py": conanfile_world or _conanfile_world, - "src/CMakeLists.txt": cmakelists_world or _cmakelists_world, + client.save({"conanfile.py": conanfile or _conanfile_world, + "src/CMakeLists.txt": cmakelists or _cmakelists_world, "src/helloworld.h": helloworld_h, "src/helloworld.cpp": helloworld_cpp, "src/worldall.h": worldall_h, @@ -219,166 +277,19 @@ def test(self): "test_package/CMakeLists.txt": test_package_cmakelists or _test_package_cmakelists, "test_package/example.cpp": test_package_example_cpp}) client.run("create .") - return client.out def basic_test(self): client = TestClient() - conanfile_greetings = textwrap.dedent(""" - from conans import ConanFile, CMake - - class GreetingsConan(ConanFile): - name = "greetings" - version = "0.0.1" - settings = "os", "compiler", "build_type", "arch" - generators = "cmake" - exports_sources = "src/*" - - def build(self): - cmake = CMake(self) - cmake.configure(source_folder="src") - cmake.build() - - def package(self): - self.copy("*.h", dst="include", src="src") - self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) - self.copy("*.a", dst="lib", keep_path=False) - - def package_info(self): - self.cpp_info.components["hello"].libs = ["hello"] - self.cpp_info.components["bye"].libs = ["bye"] - """) - hello_h = textwrap.dedent(""" - #pragma once - - void hello(std::string noun); - """) - hello_cpp = textwrap.dedent(""" - #include - #include - - #include "hello.h" - - void hello(std::string noun) { - std::cout << "Hello " << noun << "!" << std::endl; - } - """) - bye_h = textwrap.dedent(""" - #pragma once - - void bye(std::string noun); - """) - bye_cpp = textwrap.dedent(""" - #include - #include - - #include "bye.h" - - void bye(std::string noun) { - std::cout << "Bye " << noun << "!" << std::endl; - } - """) - cmakelists_greetings = textwrap.dedent(""" - cmake_minimum_required(VERSION 3.0) - project(greetings CXX) - - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_basic_setup() - - add_library(hello hello.cpp) - add_library(bye bye.cpp) - """) - test_package_greetings_conanfile = textwrap.dedent(""" - import os - from conans import ConanFile, CMake - - class GreetingsTestConan(ConanFile): - settings = "os", "compiler", "build_type", "arch" - generators = "cmake", "cmake_find_package" - - def build(self): - cmake = CMake(self) - cmake.configure() - cmake.build() - - def test(self): - os.chdir("bin") - self.run(".%sexample" % os.sep) - """) - test_package_greetings_cpp = textwrap.dedent(""" - #include - - #include "hello.h" - #include "bye.h" - - int main() { - hello("Moon"); - bye("Moon"); - } - """) - test_package_greetings_cmakelists = textwrap.dedent(""" - cmake_minimum_required(VERSION 3.0) - project(PackageTest CXX) - - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_basic_setup() - - find_package(greetings) - - add_executable(example example.cpp) - target_link_libraries(example greetings::greetings) - """) - client.save({"conanfile.py": conanfile_greetings, - "src/CMakeLists.txt": cmakelists_greetings, - "src/hello.h": hello_h, - "src/hello.cpp": hello_cpp, - "src/bye.h": bye_h, - "src/bye.cpp": bye_cpp, - "test_package/conanfile.py": test_package_greetings_conanfile, - "test_package/example.cpp": test_package_greetings_cpp, - "test_package/CMakeLists.txt": test_package_greetings_cmakelists}) - client.run("create .") + self._create_greetings(client, test=True) self.assertIn("Hello Moon!", client.out) self.assertIn("Bye Moon!", client.out) - - def component_depends_on_full_package_test(self): - out = self._test() - self.assertIn("Hello World!", out) - self.assertIn("Bye World!", out) + self._create_world(client) + self.assertIn("Hello World!", client.out) + self.assertIn("Bye World!", client.out) def find_package_general_test(self): - conanfile_greetings = textwrap.dedent(""" - from conans import ConanFile, CMake - - class GreetingsConan(ConanFile): - name = "greetings" - version = "0.0.1" - settings = "os", "compiler", "build_type", "arch" - generators = "cmake" - exports_sources = "src/*" - - def build(self): - cmake = CMake(self) - cmake.configure(source_folder="src") - cmake.build() - - def package(self): - self.copy("*.h", dst="include", src="src") - self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) - self.copy("*.a", dst="lib", keep_path=False) - - def package_info(self): - self.cpp_info.names["cmake_find_package"] = "Greetings" - self.cpp_info.components["hello"].names["cmake_find_package"] = "Hello" - self.cpp_info.components["hello"].libs = ["hello"] - self.cpp_info.components["bye"].names["cmake_find_package"] = "Bye" - self.cpp_info.components["bye"].libs = ["bye"] - """) + client = TestClient() + self._create_greetings(client, custom_names=True) conanfile_world = textwrap.dedent(""" from conans import ConanFile, CMake @@ -399,9 +310,6 @@ def build(self): def package(self): self.copy("*.h", dst="include", src="src") self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) self.copy("*.a", dst="lib", keep_path=False) def package_info(self): @@ -416,7 +324,7 @@ def package_info(self): cmakelists_world = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(world CXX) - + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() @@ -443,13 +351,14 @@ def package_info(self): add_executable(example2 example.cpp) target_link_libraries(example2 World::World) """) - out = self._test(conanfile_greetings=conanfile_greetings, - conanfile_world=conanfile_world, cmakelists_world=cmakelists_world, - test_package_cmakelists=test_package_cmakelists) - self.assertIn("Hello World!", out) - self.assertIn("Bye World!", out) + self._create_world(client, conanfile=conanfile_world, cmakelists=cmakelists_world, + test_package_cmakelists=test_package_cmakelists) + self.assertIn("Hello World!", client.out) + self.assertIn("Bye World!", client.out) def find_package_components_test(self): + client = TestClient() + self._create_greetings(client) conanfile2 = textwrap.dedent(""" from conans import ConanFile, CMake @@ -469,9 +378,6 @@ def build(self): def package(self): self.copy("*.h", dst="include", src="src") self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) self.copy("*.a", dst="lib", keep_path=False) def package_info(self): @@ -483,7 +389,7 @@ def package_info(self): cmakelists2 = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(world CXX) - + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() @@ -497,112 +403,51 @@ def package_info(self): add_library(worldall worldall.cpp) target_link_libraries(worldall helloworld greetings::bye) """) - out = self._test(conanfile_world=conanfile2, cmakelists_world=cmakelists2) - self.assertIn("Hello World!", out) - self.assertIn("Bye World!", out) + self._create_world(client, conanfile=conanfile2, cmakelists=cmakelists2) + self.assertIn("Hello World!", client.out) + self.assertIn("Bye World!", client.out) def recipe_with_components_requiring_recipe_without_components_test(self): - conanfile1 = textwrap.dedent(""" - from conans import ConanFile, CMake - - class GreetingsConan(ConanFile): - name = "greetings" - version = "0.0.1" - settings = "os", "compiler", "build_type", "arch" - generators = "cmake" - exports_sources = "src/*" - - def build(self): - cmake = CMake(self) - cmake.configure(source_folder="src") - cmake.build() - - def package(self): - self.copy("*.h", dst="include", src="src") - self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) - self.copy("*.a", dst="lib", keep_path=False) + client = TestClient() + self._create_greetings(client, components=False) - def package_info(self): - self.cpp_info.libs = ["hello", "bye"] - """) - conanfile2 = textwrap.dedent(""" - from conans import ConanFile, CMake - - class WorldConan(ConanFile): - name = "world" - version = "0.0.1" - settings = "os", "compiler", "build_type", "arch" - generators = "cmake", "cmake_find_package" - exports_sources = "src/*" - requires = "greetings/0.0.1" - - def build(self): - cmake = CMake(self) - cmake.configure(source_folder="src") - cmake.build() - - def package(self): - self.copy("*.h", dst="include", src="src") - self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) - self.copy("*.a", dst="lib", keep_path=False) - - def package_info(self): - self.cpp_info.components["helloworld"].requires = ["greetings::greetings"] - self.cpp_info.components["helloworld"].libs = ["helloworld"] - self.cpp_info.components["worldall"].requires = ["helloworld", "greetings::greetings"] - self.cpp_info.components["worldall"].libs = ["worldall"] - """) cmakelists2 = textwrap.dedent(""" - cmake_minimum_required(VERSION 3.0) - project(world CXX) + cmake_minimum_required(VERSION 3.0) + project(world CXX) - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_basic_setup() + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() - find_package(greetings COMPONENTS hello) + find_package(greetings COMPONENTS hello) - add_library(helloworld helloworld.cpp) - target_link_libraries(helloworld greetings::greetings) + add_library(helloworld helloworld.cpp) + target_link_libraries(helloworld greetings::greetings) - find_package(greetings COMPONENTS bye) + find_package(greetings COMPONENTS hello bye) - add_library(worldall worldall.cpp) - target_link_libraries(worldall helloworld greetings::greetings) - """) - out = self._test(conanfile_greetings=conanfile1, conanfile_world=conanfile2, - cmakelists_world=cmakelists2) - self.assertIn("Hello World!", out) - self.assertIn("Bye World!", out) + add_library(worldall worldall.cpp) + target_link_libraries(worldall helloworld greetings::greetings) + """) + self._create_world(client, cmakelists=cmakelists2) + self.assertIn("Hello World!", client.out) + self.assertIn("Bye World!", client.out) def component_not_found_test(self): conanfile = textwrap.dedent(""" - from conans import ConanFile, CMake + from conans import ConanFile class GreetingsConan(ConanFile): - name = "greetings" - version = "0.0.1" - settings = "os", "compiler", "build_type", "arch" - def package_info(self): self.cpp_info.components["hello"].libs = ["hello"] """) client = TestClient() client.save({"conanfile.py": conanfile}) - client.run("create conanfile.py") + client.run("create . greetings/0.0.1@") conanfile = textwrap.dedent(""" - from conans import ConanFile, CMake + from conans import ConanFile class WorldConan(ConanFile): - name = "world" - version = "0.0.1" - settings = "os", "compiler", "build_type", "arch" requires = "greetings/0.0.1" def package_info(self): @@ -610,7 +455,7 @@ def package_info(self): self.cpp_info.components["helloworld"].libs = ["helloworld"] """) client.save({"conanfile.py": conanfile}) - client.run("create conanfile.py") + client.run("create . world/0.0.1@") client.run("install world/0.0.1@ -g cmake_find_package", assert_error=True) self.assertIn("ERROR: Component 'greetings::non-existent' not found in 'greetings' " "package requirement", client.out) @@ -635,9 +480,6 @@ def build(self): def package(self): self.copy("*.h", dst="include", src="src") self.copy("*.lib", dst="lib", keep_path=False) - self.copy("*.dll", dst="bin", keep_path=False) - self.copy("*.dylib*", dst="lib", keep_path=False) - self.copy("*.so", dst="lib", keep_path=False) self.copy("*.a", dst="lib", keep_path=False) def package_info(self): @@ -646,9 +488,9 @@ def package_info(self): """) hello_h = textwrap.dedent(""" #pragma once - void hello(std::string noun); """) + hello_cpp = textwrap.dedent(""" #include #include From 94b2f5e3078db176fdfff21e1bf00118bf7fe070 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 3 Jun 2020 11:04:20 +0200 Subject: [PATCH 28/35] fix --- .../generators/cmake_components_test.py | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 447f81dd5e5..50a3e93f9cc 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -149,7 +149,7 @@ def test(self): client.run("create .") @staticmethod - def _create_world(client, conanfile=None, cmakelists=None, test_package_cmakelists=None): + def _create_world(client, conanfile=None, cmakelists=None, test_cmakelists=None): _conanfile_world = textwrap.dedent(""" from conans import ConanFile, CMake @@ -227,7 +227,7 @@ def package_info(self): add_library(worldall worldall.cpp) target_link_libraries(worldall helloworld greetings::greetings) """) - test_package_conanfile = textwrap.dedent(""" + test_conanfile = textwrap.dedent(""" import os from conans import ConanFile, CMake @@ -245,14 +245,14 @@ def test(self): self.run(".%sexample" % os.sep) self.run(".%sexample2" % os.sep) """) - test_package_example_cpp = textwrap.dedent(""" + test_example_cpp = textwrap.dedent(""" #include "worldall.h" int main() { worldAll(); } """) - _test_package_cmakelists = textwrap.dedent(""" + _test_cmakelists = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) @@ -273,9 +273,9 @@ def test(self): "src/helloworld.cpp": helloworld_cpp, "src/worldall.h": worldall_h, "src/worldall.cpp": worldall_cpp, - "test_package/conanfile.py": test_package_conanfile, - "test_package/CMakeLists.txt": test_package_cmakelists or _test_package_cmakelists, - "test_package/example.cpp": test_package_example_cpp}) + "test_package/conanfile.py": test_conanfile, + "test_package/CMakeLists.txt": test_cmakelists or _test_cmakelists, + "test_package/example.cpp": test_example_cpp}) client.run("create .") def basic_test(self): @@ -291,7 +291,7 @@ def find_package_general_test(self): client = TestClient() self._create_greetings(client, custom_names=True) - conanfile_world = textwrap.dedent(""" + conanfile = textwrap.dedent(""" from conans import ConanFile, CMake class WorldConan(ConanFile): @@ -321,7 +321,7 @@ def package_info(self): self.cpp_info.components["worldall"].requires = ["greetings::bye", "helloworld"] self.cpp_info.components["worldall"].libs = ["Worldall"] """) - cmakelists_world = textwrap.dedent(""" + cmakelists = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(world CXX) @@ -336,7 +336,7 @@ def package_info(self): add_library(Worldall worldall.cpp) target_link_libraries(Worldall Helloworld Greetings::Bye) """) - test_package_cmakelists = textwrap.dedent(""" + test_cmakelists = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(PackageTest CXX) @@ -351,8 +351,8 @@ def package_info(self): add_executable(example2 example.cpp) target_link_libraries(example2 World::World) """) - self._create_world(client, conanfile=conanfile_world, cmakelists=cmakelists_world, - test_package_cmakelists=test_package_cmakelists) + self._create_world(client, conanfile=conanfile, cmakelists=cmakelists, + test_cmakelists=test_cmakelists) self.assertIn("Hello World!", client.out) self.assertIn("Bye World!", client.out) @@ -411,7 +411,35 @@ def recipe_with_components_requiring_recipe_without_components_test(self): client = TestClient() self._create_greetings(client, components=False) - cmakelists2 = textwrap.dedent(""" + conanfile = textwrap.dedent(""" + from conans import ConanFile, CMake + + class WorldConan(ConanFile): + name = "world" + version = "0.0.1" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake_find_package", "cmake" + exports_sources = "src/*" + requires = "greetings/0.0.1" + + def build(self): + cmake = CMake(self) + cmake.configure(source_folder="src") + cmake.build() + + def package(self): + self.copy("*.h", dst="include", src="src") + self.copy("*.lib", dst="lib", keep_path=False) + self.copy("*.a", dst="lib", keep_path=False) + + def package_info(self): + self.cpp_info.components["helloworld"].requires = ["greetings::greetings"] + self.cpp_info.components["helloworld"].libs = ["helloworld"] + self.cpp_info.components["worldall"].requires = ["helloworld", + "greetings::greetings"] + self.cpp_info.components["worldall"].libs = ["worldall"] + """) + cmakelists = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(world CXX) @@ -428,7 +456,7 @@ def recipe_with_components_requiring_recipe_without_components_test(self): add_library(worldall worldall.cpp) target_link_libraries(worldall helloworld greetings::greetings) """) - self._create_world(client, cmakelists=cmakelists2) + self._create_world(client, conanfile=conanfile, cmakelists=cmakelists) self.assertIn("Hello World!", client.out) self.assertIn("Bye World!", client.out) From 76d11c23cba9222c91936afb08a4cd33f0d14475 Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 3 Jun 2020 15:35:17 +0200 Subject: [PATCH 29/35] use pkg name as prefix in variables --- .../client/generators/cmake_find_package.py | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 134b1053a9b..8c4280a1af7 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -112,21 +112,21 @@ class CMakeFindPackageGenerator(Generator): ########### COMPONENT {{ comp_name }} VARIABLES ############################################# - set({{ comp_name }}_INCLUDE_DIRS {{ comp.include_paths }}) - set({{ comp_name }}_INCLUDE_DIR {{ comp.include_path }}) - set({{ comp_name }}_INCLUDES {{ comp.include_paths }}) - set({{ comp_name }}_LIB_DIRS {{ comp.lib_paths }}) - set({{ comp_name }}_RES_DIRS {{ comp.res_paths }}) - set({{ comp_name }}_DEFINITIONS {{ comp.defines }}) - set({{ comp_name }}_COMPILE_DEFINITIONS {{ comp.compile_definitions }}) - set({{ comp_name }}_COMPILE_OPTIONS_LIST "{{ comp.cxxflags_list }}" "{{ comp.cflags_list }}") - set({{ comp_name }}_LIBS {{ comp.libs }}) - set({{ comp_name }}_SYSTEM_LIBS {{ comp.system_libs }}) - set({{ comp_name }}_FRAMEWORK_DIRS {{ comp.framework_paths }}) - set({{ comp_name }}_FRAMEWORKS {{ comp.frameworks }}) - set({{ comp_name }}_BUILD_MODULES_PATHS {{ comp.build_modules_paths }}) - set({{ comp_name }}_DEPENDENCIES {{ comp.public_deps }}) - set({{ comp_name }}_LINKER_FLAGS_LIST + set({{ pkg_name }}_{{ comp_name }}_INCLUDE_DIRS {{ comp.include_paths }}) + set({{ pkg_name }}_{{ comp_name }}_INCLUDE_DIR {{ comp.include_path }}) + set({{ pkg_name }}_{{ comp_name }}_INCLUDES {{ comp.include_paths }}) + set({{ pkg_name }}_{{ comp_name }}_LIB_DIRS {{ comp.lib_paths }}) + set({{ pkg_name }}_{{ comp_name }}_RES_DIRS {{ comp.res_paths }}) + set({{ pkg_name }}_{{ comp_name }}_DEFINITIONS {{ comp.defines }}) + set({{ pkg_name }}_{{ comp_name }}_COMPILE_DEFINITIONS {{ comp.compile_definitions }}) + set({{ pkg_name }}_{{ comp_name }}_COMPILE_OPTIONS_LIST "{{ comp.cxxflags_list }}" "{{ comp.cflags_list }}") + set({{ pkg_name }}_{{ comp_name }}_LIBS {{ comp.libs }}) + set({{ pkg_name }}_{{ comp_name }}_SYSTEM_LIBS {{ comp.system_libs }}) + set({{ pkg_name }}_{{ comp_name }}_FRAMEWORK_DIRS {{ comp.framework_paths }}) + set({{ pkg_name }}_{{ comp_name }}_FRAMEWORKS {{ comp.frameworks }}) + set({{ pkg_name }}_{{ comp_name }}_BUILD_MODULES_PATHS {{ comp.build_modules_paths }}) + set({{ pkg_name }}_{{ comp_name }}_DEPENDENCIES {{ comp.public_deps }}) + set({{ pkg_name }}_{{ comp_name }}_LINKER_FLAGS_LIST $<$,SHARED_LIBRARY>:{{ comp.sharedlinkflags_list }}> $<$,MODULE_LIBRARY>:{{ comp.sharedlinkflags_list }}> $<$,EXECUTABLE>:{{ comp.exelinkflags_list }}> @@ -158,23 +158,23 @@ class CMakeFindPackageGenerator(Generator): ########## COMPONENT {{ comp_name }} FIND LIBRARIES & FRAMEWORKS / DYNAMIC VARS ############# - set({{ comp_name }}_FRAMEWORKS_FOUND "") - conan_find_apple_frameworks({{ comp_name }}_FRAMEWORKS_FOUND "{{ '${'+comp_name+'_FRAMEWORKS}' }}" "{{ '${'+comp_name+'_FRAMEWORK_DIRS}' }}") + set({{ pkg_name }}_{{ comp_name }}_FRAMEWORKS_FOUND "") + conan_find_apple_frameworks({{ pkg_name }}_{{ comp_name }}_FRAMEWORKS_FOUND "{{ '${'+pkg_name+'_'+comp_name+'_FRAMEWORKS}' }}" "{{ '${'+pkg_name+'_'+comp_name+'_FRAMEWORK_DIRS}' }}") - set({{ comp_name }}_LIB_TARGETS "") - conan_component_library_targets({{ comp_name }}_LIB_TARGETS - "{{ '${'+comp_name+'_LIB_DIRS}' }}" - "{{ '${'+comp_name+'_LIBS}' }}" - "{{ '${'+comp_name+'_DEPENDENCIES}' }}" - "{{ '${'+comp_name+'_SYSTEM_LIBS}' }}" - "{{ '${'+comp_name+'_FRAMEWORKS_FOUND}' }}") + set({{ pkg_name }}_{{ comp_name }}_LIB_TARGETS "") + conan_component_library_targets({{ pkg_name }}_{{ comp_name }}_LIB_TARGETS + "{{ '${'+pkg_name+'_'+comp_name+'_LIB_DIRS}' }}" + "{{ '${'+pkg_name+'_'+comp_name+'_LIBS}' }}" + "{{ '${'+pkg_name+'_'+comp_name+'_DEPENDENCIES}' }}" + "{{ '${'+pkg_name+'_'+comp_name+'_SYSTEM_LIBS}' }}" + "{{ '${'+pkg_name+'_'+comp_name+'_FRAMEWORKS_FOUND}' }}") - set({{ comp_name }}_LINK_LIBS {{ '${'+comp_name+'_LIB_TARGETS}' }} {{ '${'+comp_name+'_DEPENDENCIES}' }}) + set({{ pkg_name }}_{{ comp_name }}_LINK_LIBS {{ '${'+pkg_name+'_'+comp_name+'_LIB_TARGETS}' }} {{ '${'+pkg_name+'_'+comp_name+'_DEPENDENCIES}' }}) set(CMAKE_MODULE_PATH {{ comp.build_paths }} ${CMAKE_MODULE_PATH}) set(CMAKE_PREFIX_PATH {{ comp.build_paths }} ${CMAKE_PREFIX_PATH}) - foreach(_BUILD_MODULE_PATH {{ '${'+comp_name+'_BUILD_MODULES_PATHS}' }}) + foreach(_BUILD_MODULE_PATH {{ '${'+pkg_name+'_'+comp_name+'_BUILD_MODULES_PATHS}' }}) include(${_BUILD_MODULE_PATH}) endforeach() @@ -193,15 +193,15 @@ class CMakeFindPackageGenerator(Generator): if(NOT TARGET {{ pkg_name }}::{{ comp_name }}) add_library({{ pkg_name }}::{{ comp_name }} INTERFACE IMPORTED) set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "{{ '${'+comp_name+'_INCLUDE_DIRS}' }}") + "{{ '${'+pkg_name+'_'+comp_name+'_INCLUDE_DIRS}' }}") set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_LINK_DIRECTORIES - "{{ '${'+comp_name+'_LIB_DIRS}' }}") + "{{ '${'+pkg_name+'_'+comp_name+'_LIB_DIRS}' }}") set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_LINK_LIBRARIES - "{{ '${'+comp_name+'_LINK_LIBS}' }};{{ '${'+comp_name+'_LINKER_FLAGS_LIST}' }}") + "{{ '${'+pkg_name+'_'+comp_name+'_LINK_LIBS}' }};{{ '${'+pkg_name+'_'+comp_name+'_LINKER_FLAGS_LIST}' }}") set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_COMPILE_DEFINITIONS - "{{ '${'+comp_name+'_COMPILE_DEFINITIONS}' }}") + "{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_DEFINITIONS}' }}") set_target_properties({{ pkg_name }}::{{ comp_name }} PROPERTIES INTERFACE_COMPILE_OPTIONS - "{{ '${'+comp_name+'_COMPILE_OPTIONS_LIST}' }}") + "{{ '${'+pkg_name+'_'+comp_name+'_COMPILE_OPTIONS_LIST}' }}") endif() endif() From 8d0c054fa7cd3bde7d3518b48efd43164d619dc8 Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 3 Jun 2020 15:58:14 +0200 Subject: [PATCH 30/35] reuse macro --- .../client/generators/cmake_find_package.py | 54 +++++-------------- 1 file changed, 12 insertions(+), 42 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 8c4280a1af7..0ebf59a88df 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -53,41 +53,7 @@ class CMakeFindPackageGenerator(Generator): ############################################################################################# {{ conan_message }} {{ conan_find_apple_frameworks }} - {% raw %} - function(conan_component_library_targets out_libraries_target libdir libraries dependencies system_libs frameworks) - foreach(_LIBRARY_NAME ${libraries}) - find_library(CONAN_FOUND_LIBRARY NAME ${_LIBRARY_NAME} PATHS ${libdir} - NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) - if(CONAN_FOUND_LIBRARY) - conan_message(STATUS "Conan: Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}") - if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") - # Create a micro-target for each lib/a found - set(_LIB_NAME ${_LIBRARY_NAME}) - if(NOT TARGET ${_LIB_NAME}) - # Create a micro-target for each lib/a found - add_library(${_LIB_NAME} UNKNOWN IMPORTED) - set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION ${CONAN_FOUND_LIBRARY}) - else() - conan_message(STATUS "Conan: Skipping already existing target: ${_LIB_NAME}") - endif() - list(APPEND _out_libraries_target ${_LIB_NAME}) - endif() - else() - conan_message(FATAL_ERROR "Conan: Component library ${_LIBRARY_NAME} not found in paths: ${libdir}") - endif() - unset(CONAN_FOUND_LIBRARY CACHE) - endforeach() - - # Add all dependencies to all targets - string(REPLACE " " ";" deps_list "${dependencies}") - foreach(_out_library_target ${_out_libraries_target}) - set_property(TARGET ${_out_library_target} PROPERTY INTERFACE_LINK_LIBRARIES "${deps_list};${system_libs};${frameworks}") - endforeach() - - conan_message(STATUS "Conan: Component library targets: ${_out_libraries_target}") - set(${out_libraries_target} ${_out_libraries_target} PARENT_SCOPE) - endfunction() - {% endraw %} + {{ conan_package_library_targets }} ########### FOUND PACKAGE ################################################################### ############################################################################################# @@ -162,12 +128,15 @@ class CMakeFindPackageGenerator(Generator): conan_find_apple_frameworks({{ pkg_name }}_{{ comp_name }}_FRAMEWORKS_FOUND "{{ '${'+pkg_name+'_'+comp_name+'_FRAMEWORKS}' }}" "{{ '${'+pkg_name+'_'+comp_name+'_FRAMEWORK_DIRS}' }}") set({{ pkg_name }}_{{ comp_name }}_LIB_TARGETS "") - conan_component_library_targets({{ pkg_name }}_{{ comp_name }}_LIB_TARGETS - "{{ '${'+pkg_name+'_'+comp_name+'_LIB_DIRS}' }}" - "{{ '${'+pkg_name+'_'+comp_name+'_LIBS}' }}" - "{{ '${'+pkg_name+'_'+comp_name+'_DEPENDENCIES}' }}" - "{{ '${'+pkg_name+'_'+comp_name+'_SYSTEM_LIBS}' }}" - "{{ '${'+pkg_name+'_'+comp_name+'_FRAMEWORKS_FOUND}' }}") + set({{ pkg_name }}_{{ comp_name }}_NOT_USED "") + set({{ pkg_name }}_{{ comp_name }}_LIBS_FRAMEWORKS_DEPS {{ '${'+pkg_name+'_'+comp_name+'_FRAMEWORKS_FOUND}' }} {{ '${'+pkg_name+'_'+comp_name+'_SYSTEM_LIBS}' }} {{ '${'+pkg_name+'_'+comp_name+'_DEPENDENCIES}' }}) + conan_package_library_targets("{{ '${'+pkg_name+'_'+comp_name+'_LIBS}' }}" + "{{ '${'+pkg_name+'_'+comp_name+'_LIB_DIRS}' }}" + "{{ '${'+pkg_name+'_'+comp_name+'_LIBS_FRAMEWORKS_DEPS}' }}" + {{ pkg_name }}_{{ comp_name }}_NOT_USED + {{ pkg_name }}_{{ comp_name }}_LIB_TARGETS + "" + "{{ pkg_name }}_{{ comp_name }}") set({{ pkg_name }}_{{ comp_name }}_LINK_LIBS {{ '${'+pkg_name+'_'+comp_name+'_LIB_TARGETS}' }} {{ '${'+pkg_name+'_'+comp_name+'_DEPENDENCIES}' }}) @@ -286,7 +255,8 @@ def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): pkg_public_deps=pkg_public_deps, components=components, conan_message=CMakeFindPackageCommonMacros.conan_message, - conan_find_apple_frameworks=CMakeFindPackageCommonMacros.apple_frameworks_macro) + conan_find_apple_frameworks=CMakeFindPackageCommonMacros.apple_frameworks_macro, + conan_package_library_targets=CMakeFindPackageCommonMacros.conan_package_library_targets) else: # The common macros macros_and_functions = "\n".join([ From bfb52bab768e5bf3aedb9d062c21bb7f52e78517 Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 3 Jun 2020 17:40:24 +0200 Subject: [PATCH 31/35] find_package(COMPONENTS) check and test --- .../client/generators/cmake_find_package.py | 19 +++++- .../generators/cmake_components_test.py | 58 ++++++++++++++++++- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 0ebf59a88df..8cc165a9c5b 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -28,6 +28,12 @@ class CMakeFindPackageGenerator(Generator): {name}_VERSION VERSION_VAR {name}_VERSION) mark_as_advanced({name}_FOUND {name}_VERSION) + if({name}_FIND_COMPONENTS) + foreach(_FIND_COMPONENT ${{{name}_FIND_COMPONENTS}}) + conan_message(FATAL_ERROR "Conan: Component '${{_FIND_COMPONENT}}' NOT found in package '{name}'") + endforeach() + endif() + {find_libraries_block} if(NOT ${{CMAKE_VERSION}} VERSION_LESS "3.0") # Target approach @@ -63,17 +69,26 @@ class CMakeFindPackageGenerator(Generator): conan_message(STATUS "Conan: Using autogenerated Find{{ pkg_name }}.cmake") set({{ pkg_name }}_FOUND 1) set({{ pkg_name }}_VERSION "{{ pkg_version }}") + set({{ pkg_name }}_COMPONENTS {{ pkg_components }}) find_package_handle_standard_args({{ pkg_name }} REQUIRED_VARS {{ pkg_name }}_VERSION VERSION_VAR {{ pkg_name }}_VERSION) mark_as_advanced({{ pkg_name }}_FOUND {{ pkg_name }}_VERSION) + if({{ pkg_name }}_FIND_COMPONENTS) + foreach(_FIND_COMPONENT {{ '${'+pkg_name+'_FIND_COMPONENTS}' }}) + list(FIND {{ pkg_name }}_COMPONENTS "{{ pkg_name }}::${_FIND_COMPONENT}" _index) + if(${_index} EQUAL -1) + conan_message(FATAL_ERROR "Conan: Component '${_FIND_COMPONENT}' NOT found in package '{{ pkg_name }}'") + else() + conan_message(STATUS "Conan: Component '${_FIND_COMPONENT}' found in package '{{ pkg_name }}'") + endif() + endforeach() + endif() ########### VARIABLES ####################################################################### ############################################################################################# - set({{ pkg_name }}_COMPONENTS {{ pkg_components }}) - {%- for comp_name, comp in components %} ########### COMPONENT {{ comp_name }} VARIABLES ############################################# diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 50a3e93f9cc..52f6f760780 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -451,12 +451,30 @@ def package_info(self): add_library(helloworld helloworld.cpp) target_link_libraries(helloworld greetings::greetings) - find_package(greetings COMPONENTS hello bye) + find_package(greetings COMPONENTS bye) add_library(worldall worldall.cpp) target_link_libraries(worldall helloworld greetings::greetings) """) - self._create_world(client, conanfile=conanfile, cmakelists=cmakelists) + with self.assertRaises(Exception): + self._create_world(client, conanfile=conanfile, cmakelists=cmakelists) + self.assertIn("Conan: Component hello NOT found in package greetings", client.out) + cmakelists2 = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(world CXX) + + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + conan_basic_setup() + + find_package(greetings) + + add_library(helloworld helloworld.cpp) + target_link_libraries(helloworld greetings::greetings) + + add_library(worldall worldall.cpp) + target_link_libraries(worldall helloworld greetings::greetings) + """) + self._create_world(client, conanfile=conanfile, cmakelists=cmakelists2) self.assertIn("Hello World!", client.out) self.assertIn("Bye World!", client.out) @@ -488,6 +506,42 @@ def package_info(self): self.assertIn("ERROR: Component 'greetings::non-existent' not found in 'greetings' " "package requirement", client.out) + def component_not_found_cmake_test(self): + conanfile = textwrap.dedent(""" + from conans import ConanFile + + class GreetingsConan(ConanFile): + def package_info(self): + self.cpp_info.components["hello"].libs = ["hello"] + """) + client = TestClient() + client.save({"conanfile.py": conanfile}) + client.run("create . greetings/0.0.1@") + + conanfile = textwrap.dedent(""" + from conans import ConanFile, CMake + + class ConsumerConan(ConanFile): + generators = "cmake_find_package" + requires = "greetings/0.0.1" + + def build(self): + cmake = CMake(self) + cmake.configure() + """) + cmakelists = textwrap.dedent(""" + cmake_minimum_required(VERSION 3.0) + project(Consumer CXX) + + find_package(greetings COMPONENTS hello) + find_package(greetings COMPONENTS non-existent) + """) + client.save({"conanfile.py": conanfile, "CMakeLists.txt": cmakelists}) + client.run("install .") + client.run("build .", assert_error=True) + self.assertIn("Conan: Component 'hello' found in package 'greetings'", client.out) + self.assertIn("Conan: Component 'non-existent' NOT found in package 'greetings'", client.out) + def same_names_test(self): client = TestClient() conanfile_greetings = textwrap.dedent(""" From 435860508298f31326e8e41dab2e8edf8aaa01b3 Mon Sep 17 00:00:00 2001 From: danimtb Date: Wed, 3 Jun 2020 19:13:58 +0200 Subject: [PATCH 32/35] fix textwrap for python 2 and a test --- conans/test/functional/generators/cmake_components_test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index 52f6f760780..d866735afa8 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -83,7 +83,8 @@ def package_info(self): info = textwrap.dedent(""" self.cpp_info.libs = ["hello", "bye"] """) - conanfile_greetings = conanfile_greetings % textwrap.indent(info, " ") + wrapper = textwrap.TextWrapper(width=81, initial_indent=" ", subsequent_indent=" ") + conanfile_greetings = conanfile_greetings % wrapper.fill(info) cmakelists_greetings = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) @@ -458,7 +459,7 @@ def package_info(self): """) with self.assertRaises(Exception): self._create_world(client, conanfile=conanfile, cmakelists=cmakelists) - self.assertIn("Conan: Component hello NOT found in package greetings", client.out) + self.assertIn("Conan: Component 'hello' NOT found in package 'greetings'", client.out) cmakelists2 = textwrap.dedent(""" cmake_minimum_required(VERSION 3.0) project(world CXX) From 5a60e3720f68600565bf62fe429703a8f677b701 Mon Sep 17 00:00:00 2001 From: danimtb Date: Thu, 4 Jun 2020 11:20:41 +0200 Subject: [PATCH 33/35] remove find components check in old implementation --- .../client/generators/cmake_find_package.py | 6 ------ .../generators/cmake_components_test.py | 20 +------------------ 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index 8cc165a9c5b..a1324f1838c 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -28,12 +28,6 @@ class CMakeFindPackageGenerator(Generator): {name}_VERSION VERSION_VAR {name}_VERSION) mark_as_advanced({name}_FOUND {name}_VERSION) - if({name}_FIND_COMPONENTS) - foreach(_FIND_COMPONENT ${{{name}_FIND_COMPONENTS}}) - conan_message(FATAL_ERROR "Conan: Component '${{_FIND_COMPONENT}}' NOT found in package '{name}'") - endforeach() - endif() - {find_libraries_block} if(NOT ${{CMAKE_VERSION}} VERSION_LESS "3.0") # Target approach diff --git a/conans/test/functional/generators/cmake_components_test.py b/conans/test/functional/generators/cmake_components_test.py index d866735afa8..24f95b44f65 100644 --- a/conans/test/functional/generators/cmake_components_test.py +++ b/conans/test/functional/generators/cmake_components_test.py @@ -457,25 +457,7 @@ def package_info(self): add_library(worldall worldall.cpp) target_link_libraries(worldall helloworld greetings::greetings) """) - with self.assertRaises(Exception): - self._create_world(client, conanfile=conanfile, cmakelists=cmakelists) - self.assertIn("Conan: Component 'hello' NOT found in package 'greetings'", client.out) - cmakelists2 = textwrap.dedent(""" - cmake_minimum_required(VERSION 3.0) - project(world CXX) - - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_basic_setup() - - find_package(greetings) - - add_library(helloworld helloworld.cpp) - target_link_libraries(helloworld greetings::greetings) - - add_library(worldall worldall.cpp) - target_link_libraries(worldall helloworld greetings::greetings) - """) - self._create_world(client, conanfile=conanfile, cmakelists=cmakelists2) + self._create_world(client, conanfile=conanfile, cmakelists=cmakelists) self.assertIn("Hello World!", client.out) self.assertIn("Bye World!", client.out) From 9bb523a01efae0ab97f5a9ddce9d1cad92f6206f Mon Sep 17 00:00:00 2001 From: danimtb Date: Thu, 4 Jun 2020 17:34:05 +0200 Subject: [PATCH 34/35] keep global variables --- .../client/generators/cmake_find_package.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index a1324f1838c..d4288f0a538 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -83,6 +83,29 @@ class CMakeFindPackageGenerator(Generator): ########### VARIABLES ####################################################################### ############################################################################################# + set({{ pkg_name }}_INCLUDE_DIRS {{ pkg.include_paths }}) + set({{ pkg_name }}_INCLUDE_DIR {{ pkg.include_path }}) + set({{ pkg_name }}_INCLUDES {{ pkg.include_paths }}) + set({{ pkg_name }}_LIB_DIRS {{ pkg.lib_paths }}) + set({{ pkg_name }}_RES_DIRS {{ pkg.res_paths }}) + set({{ pkg_name }}_DEFINITIONS {{ pkg.defines }}) + set({{ pkg_name }}_LINKER_FLAGS_LIST + $<$,SHARED_LIBRARY>:{{ pkg.sharedlinkflags_list }}> + $<$,MODULE_LIBRARY>:{{ pkg.sharedlinkflags_list }}> + $<$,EXECUTABLE>:{{ pkg.exelinkflags_list }}> + ) + set({{ pkg_name }}_COMPILE_DEFINITIONS {{ pkg.compile_definitions }}) + set({{ pkg_name }}_COMPILE_OPTIONS_LIST "{{ pkg.cxxflags_list }}" "{{ pkg.cflags_list }}") + set({{ pkg_name }}_LIBRARIES_TARGETS "") # Will be filled later, if CMake 3 + set({{ pkg_name }}_LIBRARIES "") # Will be filled later + set({{ pkg_name }}_LIBS "") # Same as {{ pkg_name }}_LIBRARIES + set({{ pkg_name }}_LIBRARY_LIST {{ pkg.libs }}) + set({{ pkg_name }}_SYSTEM_LIBS {{ pkg.system_libs }}) + set({{ pkg_name }}_FRAMEWORK_DIRS {{ pkg.framework_paths }}) + set({{ pkg_name }}_FRAMEWORKS {{ pkg.frameworks }}) + set({{ pkg_name }}_FRAMEWORKS_FOUND "") # Will be filled later + set({{ pkg_name }}_BUILD_MODULES_PATHS {{ pkg.build_modules_paths }}) + {%- for comp_name, comp in components %} ########### COMPONENT {{ comp_name }} VARIABLES ############################################# @@ -257,10 +280,12 @@ def _find_for_dep(self, pkg_name, pkg_findname, 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 = DepsCppCmake(cpp_info) return self.find_components_tpl.render( pkg_name=pkg_findname, pkg_version=pkg_version, pkg_components=pkg_components, + pkg=pkg, pkg_public_deps=pkg_public_deps, components=components, conan_message=CMakeFindPackageCommonMacros.conan_message, From 6daf6971e3b05a53247dbf42f821d77c5d77242e Mon Sep 17 00:00:00 2001 From: danimtb Date: Fri, 5 Jun 2020 10:48:04 +0200 Subject: [PATCH 35/35] include and populate all global variables --- .../client/generators/cmake_find_package.py | 35 +++++-------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/conans/client/generators/cmake_find_package.py b/conans/client/generators/cmake_find_package.py index d4288f0a538..cc313f75e8d 100644 --- a/conans/client/generators/cmake_find_package.py +++ b/conans/client/generators/cmake_find_package.py @@ -83,28 +83,7 @@ class CMakeFindPackageGenerator(Generator): ########### VARIABLES ####################################################################### ############################################################################################# - set({{ pkg_name }}_INCLUDE_DIRS {{ pkg.include_paths }}) - set({{ pkg_name }}_INCLUDE_DIR {{ pkg.include_path }}) - set({{ pkg_name }}_INCLUDES {{ pkg.include_paths }}) - set({{ pkg_name }}_LIB_DIRS {{ pkg.lib_paths }}) - set({{ pkg_name }}_RES_DIRS {{ pkg.res_paths }}) - set({{ pkg_name }}_DEFINITIONS {{ pkg.defines }}) - set({{ pkg_name }}_LINKER_FLAGS_LIST - $<$,SHARED_LIBRARY>:{{ pkg.sharedlinkflags_list }}> - $<$,MODULE_LIBRARY>:{{ pkg.sharedlinkflags_list }}> - $<$,EXECUTABLE>:{{ pkg.exelinkflags_list }}> - ) - set({{ pkg_name }}_COMPILE_DEFINITIONS {{ pkg.compile_definitions }}) - set({{ pkg_name }}_COMPILE_OPTIONS_LIST "{{ pkg.cxxflags_list }}" "{{ pkg.cflags_list }}") - set({{ pkg_name }}_LIBRARIES_TARGETS "") # Will be filled later, if CMake 3 - set({{ pkg_name }}_LIBRARIES "") # Will be filled later - set({{ pkg_name }}_LIBS "") # Same as {{ pkg_name }}_LIBRARIES - set({{ pkg_name }}_LIBRARY_LIST {{ pkg.libs }}) - set({{ pkg_name }}_SYSTEM_LIBS {{ pkg.system_libs }}) - set({{ pkg_name }}_FRAMEWORK_DIRS {{ pkg.framework_paths }}) - set({{ pkg_name }}_FRAMEWORKS {{ pkg.frameworks }}) - set({{ pkg_name }}_FRAMEWORKS_FOUND "") # Will be filled later - set({{ pkg_name }}_BUILD_MODULES_PATHS {{ pkg.build_modules_paths }}) + {{ global_target_variables }} {%- for comp_name, comp in components %} @@ -275,17 +254,21 @@ def _find_for_dep(self, pkg_name, pkg_findname, cpp_info): pkg_version = cpp_info.version pkg_public_deps = [self._get_name(self.deps_build_info[public_dep]) for public_dep in cpp_info.public_deps] + pkg_public_deps_names = ";".join(["{n}::{n}".format(n=n) for n in pkg_public_deps]) if cpp_info.components: components = self._get_components(pkg_name, pkg_findname, 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 = DepsCppCmake(cpp_info) + pkg_info = DepsCppCmake(cpp_info) + global_target_variables = target_template.format(name=pkg_findname, deps=pkg_info, + build_type_suffix="", + deps_names=pkg_public_deps_names) return self.find_components_tpl.render( pkg_name=pkg_findname, pkg_version=pkg_version, pkg_components=pkg_components, - pkg=pkg, + global_target_variables=global_target_variables, pkg_public_deps=pkg_public_deps, components=components, conan_message=CMakeFindPackageCommonMacros.conan_message, @@ -306,12 +289,10 @@ def _find_for_dep(self, pkg_name, pkg_findname, 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_names = ";".join(["{n}::{n}".format(n=n) for n in pkg_public_deps]) - deps = DepsCppCmake(dep_cpp_info) find_libraries_block = target_template.format(name=pkg_findname, deps=deps, build_type_suffix="", - deps_names=deps_names) + deps_names=pkg_public_deps_names) # The find_transitive_dependencies block find_dependencies_block = ""