diff --git a/conan/tools/cmake/cmakedeps.py b/conan/tools/cmake/cmakedeps.py index 304cf62644b..baf8d0009a9 100644 --- a/conan/tools/cmake/cmakedeps.py +++ b/conan/tools/cmake/cmakedeps.py @@ -83,10 +83,8 @@ """) -target_template = """ +variables_template = """ set({name}_INCLUDE_DIRS{build_type_suffix} {deps.include_paths}) -set({name}_INCLUDE_DIR{build_type_suffix} {deps.include_path}) -set({name}_INCLUDES{build_type_suffix} {deps.include_paths}) set({name}_RES_DIRS{build_type_suffix} {deps.res_paths}) set({name}_DEFINITIONS{build_type_suffix} {deps.defines}) set({name}_LINKER_FLAGS{build_type_suffix}_LIST @@ -98,44 +96,31 @@ set({name}_COMPILE_OPTIONS{build_type_suffix}_LIST "{deps.cxxflags_list}" "{deps.cflags_list}") set({name}_COMPILE_OPTIONS_C{build_type_suffix} "{deps.cflags_list}") set({name}_COMPILE_OPTIONS_CXX{build_type_suffix} "{deps.cxxflags_list}") -set({name}_LIBRARIES_TARGETS{build_type_suffix} "") # Will be filled later, if CMake 3 -set({name}_LIBRARIES{build_type_suffix} "") # Will be filled later -set({name}_LIBS{build_type_suffix} "") # Same as {name}_LIBRARIES +set({name}_LIB_DIRS{build_type_suffix} {deps.lib_paths}) +set({name}_LIBS{build_type_suffix} {deps.libs}) set({name}_SYSTEM_LIBS{build_type_suffix} {deps.system_libs}) set({name}_FRAMEWORK_DIRS{build_type_suffix} {deps.framework_paths}) set({name}_FRAMEWORKS{build_type_suffix} {deps.frameworks}) -set({name}_FRAMEWORKS_FOUND{build_type_suffix} "") # Will be filled later set({name}_BUILD_MODULES_PATHS{build_type_suffix} {deps.build_modules_paths}) +""" -conan_find_apple_frameworks({name}_FRAMEWORKS_FOUND{build_type_suffix} "${{{name}_FRAMEWORKS{build_type_suffix}}}" "${{{name}_FRAMEWORK_DIRS{build_type_suffix}}}") -mark_as_advanced({name}_INCLUDE_DIRS{build_type_suffix} - {name}_INCLUDE_DIR{build_type_suffix} - {name}_INCLUDES{build_type_suffix} - {name}_DEFINITIONS{build_type_suffix} - {name}_LINKER_FLAGS{build_type_suffix}_LIST - {name}_COMPILE_DEFINITIONS{build_type_suffix} - {name}_COMPILE_OPTIONS{build_type_suffix}_LIST - {name}_LIBRARIES{build_type_suffix} - {name}_LIBS{build_type_suffix} - {name}_LIBRARIES_TARGETS{build_type_suffix}) - -# Find the real .lib/.a and add them to {name}_LIBS and {name}_LIBRARY_LIST -set({name}_LIBRARY_LIST{build_type_suffix} {deps.libs}) -set({name}_LIB_DIRS{build_type_suffix} {deps.lib_paths}) +dynamic_variables_template = """ +set({name}_FRAMEWORKS_FOUND{build_type_suffix} "") # Will be filled later +conan_find_apple_frameworks({name}_FRAMEWORKS_FOUND{build_type_suffix} "${{{name}_FRAMEWORKS{build_type_suffix}}}" "${{{name}_FRAMEWORK_DIRS{build_type_suffix}}}") # Gather all the libraries that should be linked to the targets (do not touch existing variables): set(_{name}_DEPENDENCIES{build_type_suffix} "${{{name}_FRAMEWORKS_FOUND{build_type_suffix}}} ${{{name}_SYSTEM_LIBS{build_type_suffix}}} {deps_names}") -conan_package_library_targets("${{{name}_LIBRARY_LIST{build_type_suffix}}}" # libraries - "${{{name}_LIB_DIRS{build_type_suffix}}}" # package_libdir +set({name}_LIBRARIES_TARGETS{build_type_suffix} "") # Will be filled later, if CMake 3 +set({name}_LIBRARIES{build_type_suffix} "") # Will be filled later +conan_package_library_targets("${{{name}_LIBS{build_type_suffix}}}" # libraries + "${{{name}_LIB_DIRS{build_type_suffix}}}" # package_libdir "${{_{name}_DEPENDENCIES{build_type_suffix}}}" # deps - {name}_LIBRARIES{build_type_suffix} # out_libraries - {name}_LIBRARIES_TARGETS{build_type_suffix} # out_libraries_targets - "{build_type_suffix}" # build_type - "{name}") # package_name - -set({name}_LIBS{build_type_suffix} ${{{name}_LIBRARIES{build_type_suffix}}}) + {name}_LIBRARIES{build_type_suffix} # out_libraries + {name}_LIBRARIES_TARGETS{build_type_suffix} # out_libraries_targets + "{build_type_suffix}" # build_type + "{name}") # package_name foreach(_FRAMEWORK ${{{name}_FRAMEWORKS_FOUND{build_type_suffix}}}) list(APPEND {name}_LIBRARIES_TARGETS{build_type_suffix} ${{_FRAMEWORK}}) @@ -289,8 +274,13 @@ class CMakeDeps(object): # Load the debug and release library finders get_filename_component(_DIR "${{CMAKE_CURRENT_LIST_FILE}}" PATH) - file(GLOB CONFIG_FILES "${{_DIR}}/{filename}Target-*.cmake") + file(GLOB DATA_FILES "${{_DIR}}/{filename}-*-*-data.cmake") + + foreach(f ${{DATA_FILES}}) + include(${{f}}) + endforeach() + file(GLOB CONFIG_FILES "${{_DIR}}/{filename}Target-*.cmake") foreach(f ${{CONFIG_FILES}}) include(${{f}}) endforeach() @@ -356,15 +346,11 @@ class CMakeDeps(object): endif() """) - components_target_build_type_tpl = Template(textwrap.dedent("""\ - ########## MACROS ########################################################################### - ############################################################################################# - include(${CMAKE_CURRENT_LIST_DIR}/cmakedeps_macros.cmake) - + components_variables_tpl = Template(textwrap.dedent("""\ ########### VARIABLES ####################################################################### ############################################################################################# - {{ global_target_variables }} + {{ global_variables }} set({{ pkg_name }}_COMPONENTS_{{ build_type }} {{ pkg_components }}) {%- for comp_name, comp in components %} @@ -372,8 +358,6 @@ class CMakeDeps(object): ########### COMPONENT {{ comp_name }} VARIABLES ############################################# set({{ pkg_name }}_{{ comp_name }}_INCLUDE_DIRS_{{ build_type }} {{ comp.include_paths }}) - set({{ pkg_name }}_{{ comp_name }}_INCLUDE_DIR_{{ build_type }} {{ comp.include_path }}) - set({{ pkg_name }}_{{ comp_name }}_INCLUDES_{{ build_type }} {{ comp.include_paths }}) set({{ pkg_name }}_{{ comp_name }}_LIB_DIRS_{{ build_type }} {{ comp.lib_paths }}) set({{ pkg_name }}_{{ comp_name }}_RES_DIRS_{{ build_type }} {{ comp.res_paths }}) set({{ pkg_name }}_{{ comp_name }}_DEFINITIONS_{{ build_type }} {{ comp.defines }}) @@ -391,6 +375,20 @@ class CMakeDeps(object): $<$,MODULE_LIBRARY>:{{ comp.sharedlinkflags_list }}> $<$,EXECUTABLE>:{{ comp.exelinkflags_list }}> ) + {%- endfor %} + """)) + + components_dynamic_variables_tpl = Template(textwrap.dedent("""\ + ########## MACROS ########################################################################### + ############################################################################################# + include(${CMAKE_CURRENT_LIST_DIR}/cmakedeps_macros.cmake) + + ########### VARIABLES ####################################################################### + ############################################################################################# + + {{ global_dynamic_variables }} + + {%- for comp_name, comp in components %} ########## COMPONENT {{ comp_name }} FIND LIBRARIES & FRAMEWORKS / DYNAMIC VARS ############# @@ -426,6 +424,14 @@ class CMakeDeps(object): add_library({{ pkg_name }}::{{ pkg_name }} INTERFACE IMPORTED) endif() + # Load the debug and release variables + get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + file(GLOB DATA_FILES "${_DIR}/{{ pkg_filename }}-*-*-data.cmake") + + foreach(f ${DATA_FILES}) + include(${f}) + endforeach() + # Load the debug and release library finders get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) file(GLOB CONFIG_FILES "${_DIR}/{{ pkg_filename }}Target-*.cmake") @@ -536,7 +542,7 @@ class CMakeDeps(object): def __init__(self, conanfile): self._conanfile = conanfile - + self.arch = str(self._conanfile.settings.arch) self.configuration = str(self._conanfile.settings.build_type) self.configurations = [v for v in conanfile.settings.build_type.values_range if v != "None"] # FIXME: Ugly way to define the output path @@ -663,6 +669,24 @@ def content(self): config_version = self.config_version_template.format(version=pkg_version) ret[self._config_version_filename(pkg_filename)] = config_version if not cpp_info.components: + # If any config matches the build_type one, add it to the cpp_info + dep_cpp_info = extend(cpp_info, build_type.lower()) + deps = DepsCppCmake(dep_cpp_info, self.name) + variables = { + "{name}-{build_type}-{arch}-data.cmake".format(name=pkg_filename, + build_type=self.configuration.lower(), + arch=self.arch): + variables_template.format(name=pkg_findname, deps=deps, + build_type_suffix=build_type_suffix) + } + dynamic_variables = { + "{}Target-{}.cmake".format(pkg_filename, self.configuration.lower()): + dynamic_variables_template.format(name=pkg_findname, deps=deps, + build_type_suffix=build_type_suffix, + deps_names=deps_names) + } + ret.update(variables) + ret.update(dynamic_variables) ret[self._config_filename(pkg_filename)] = self._config( filename=pkg_filename, name=pkg_findname, @@ -671,14 +695,6 @@ def content(self): ) ret["{}Targets.cmake".format(pkg_filename)] = self.targets_template.format( filename=pkg_filename, name=pkg_findname) - - # If any config matches the build_type one, add it to the cpp_info - dep_cpp_info = extend(cpp_info, build_type.lower()) - deps = DepsCppCmake(dep_cpp_info, self.name) - find_lib = target_template.format(name=pkg_findname, deps=deps, - build_type_suffix=build_type_suffix, - deps_names=deps_names) - ret["{}Target-{}.cmake".format(pkg_filename, self.configuration.lower())] = find_lib else: cpp_info = extend(cpp_info, build_type.lower()) pkg_info = DepsCppCmake(cpp_info, self.name) @@ -686,17 +702,27 @@ def content(self): # 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)]) - global_target_variables = target_template.format(name=pkg_findname, deps=pkg_info, - build_type_suffix=build_type_suffix, - deps_names=deps_names) - variables = self.components_target_build_type_tpl.render( - pkg_name=pkg_findname, - global_target_variables=global_target_variables, - pkg_components=pkg_components, - build_type=build_type, - components=components - ) - ret["{}Target-{}.cmake".format(pkg_filename, build_type.lower())] = variables + global_variables = variables_template.format(name=pkg_findname, deps=pkg_info, + build_type_suffix=build_type_suffix, + deps_names=deps_names) + variables = { + "{}-{}-{}-data.cmake".format(pkg_filename, build_type.lower(), self.arch): + self.components_variables_tpl.render( + pkg_name=pkg_findname, global_variables=global_variables, + pkg_components=pkg_components, build_type=build_type, components=components) + } + ret.update(variables) + global_dynamic_variables = dynamic_variables_template.format(name=pkg_findname, + deps=pkg_info, + build_type_suffix=build_type_suffix, + deps_names=deps_names) + dynamic_variables = { + "{}Target-{}.cmake".format(pkg_filename, build_type.lower()): + self.components_dynamic_variables_tpl.render( + pkg_name=pkg_findname, global_dynamic_variables=global_dynamic_variables, + pkg_components=pkg_components, build_type=build_type, components=components) + } + ret.update(dynamic_variables) targets = self.components_targets_tpl.render( pkg_name=pkg_findname, pkg_filename=pkg_filename, diff --git a/conans/test/unittests/tools/cmake/test_cmakedeps.py b/conans/test/unittests/tools/cmake/test_cmakedeps.py index 99b96cc1ef9..d35252478cd 100644 --- a/conans/test/unittests/tools/cmake/test_cmakedeps.py +++ b/conans/test/unittests/tools/cmake/test_cmakedeps.py @@ -17,6 +17,8 @@ def test_cpp_info_name_cmakedeps(): "compiler": ["gcc"], "build_type": ["Release"], "arch": ["x86"]}), EnvValues()) + conanfile.settings.build_type = "Release" + conanfile.settings.arch = "x86" cpp_info = CppInfo("mypkg", "dummy_root_folder1") cpp_info.names["cmake_find_package_multi"] = "MySuperPkg1" @@ -26,6 +28,7 @@ def test_cpp_info_name_cmakedeps(): cmakedeps = CMakeDeps(conanfile) files = cmakedeps.content assert "TARGET MySuperPkg1::MySuperPkg1" in files["ComplexFileName1Config.cmake"] + assert "set(MySuperPkg1_INCLUDE_DIRS_RELEASE )" in files["ComplexFileName1-release-x86-data.cmake"] with pytest.raises(ConanException, match="'mypkg' defines information for 'cmake_find_package_multi'"): @@ -38,8 +41,10 @@ def test_cpp_info_name_cmakedeps_components(): conanfile.settings = "os", "compiler", "build_type", "arch" conanfile.initialize(Settings({"os": ["Windows"], "compiler": ["gcc"], - "build_type": ["Release"], - "arch": ["x86"]}), EnvValues()) + "build_type": ["Release", "Debug"], + "arch": ["x86", "x64"]}), EnvValues()) + conanfile.settings.build_type = "Debug" + conanfile.settings.arch = "x64" cpp_info = CppInfo("mypkg", "dummy_root_folder1") cpp_info.names["cmake_find_package_multi"] = "GlobakPkgName1" @@ -50,6 +55,8 @@ def test_cpp_info_name_cmakedeps_components(): cmakedeps = CMakeDeps(conanfile) files = cmakedeps.content assert "TARGET GlobakPkgName1::MySuperPkg1" in files["ComplexFileName1Config.cmake"] + assert "set(GlobakPkgName1_INCLUDE_DIRS_DEBUG )" in files["ComplexFileName1-debug-x64-data.cmake"] + assert "set(GlobakPkgName1_MySuperPkg1_INCLUDE_DIRS_DEBUG )" in files["ComplexFileName1-debug-x64-data.cmake"] with pytest.raises(ConanException, match="'mypkg' defines information for 'cmake_find_package_multi'"):