From 3733be8723d89ee486937c4d177df4f9829ef9d3 Mon Sep 17 00:00:00 2001 From: Luis Date: Mon, 18 Jul 2022 17:43:53 +0200 Subject: [PATCH 1/3] not global cpp --- .../templates/target_configuration.py | 14 ++++++++++++- .../cmake/cmakedeps/templates/target_data.py | 20 +++++++++++++------ .../cmakedeps/test_cmakedeps_build_modules.py | 7 +++++-- .../cmake/cmakedeps/test_cmakedeps.py | 13 +++++++++--- .../unittests/tools/cmake/test_cmakedeps.py | 12 ++++++----- 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/conan/tools/cmake/cmakedeps/templates/target_configuration.py b/conan/tools/cmake/cmakedeps/templates/target_configuration.py index 277b5814be6..f969bdd253d 100644 --- a/conan/tools/cmake/cmakedeps/templates/target_configuration.py +++ b/conan/tools/cmake/cmakedeps/templates/target_configuration.py @@ -112,7 +112,7 @@ def template(self): {%- endfor %} - + {% if not components_names %} ########## GLOBAL TARGET PROPERTIES {{ configuration }} ######################################## set_property(TARGET {{root_target_name}} PROPERTY INTERFACE_LINK_LIBRARIES @@ -139,6 +139,9 @@ def template(self): PROPERTY INTERFACE_LINK_DIRECTORIES $<$:${{'{'}}{{pkg_name}}_LIB_DIRS{{config_suffix}}}> APPEND) {%- endif %} + + {%- else %} + ########## COMPONENTS TARGET PROPERTIES {{ configuration }} ######################################## {%- for comp_variable_name, comp_target_name in components_names %} @@ -168,6 +171,15 @@ def template(self): {%- endfor %} + ########## AGGREGATED GLOBAL TARGET WITH THE COMPONENTS ##################### + {%- for comp_variable_name, comp_target_name in components_names %} + + target_link_libraries({{root_target_name}} INTERFACE {{ comp_target_name }}) + + {%- endfor %} + + {%- endif %} + """) def get_declared_components_targets_names(self): diff --git a/conan/tools/cmake/cmakedeps/templates/target_data.py b/conan/tools/cmake/cmakedeps/templates/target_data.py index 34c459c1282..8815576bd6e 100644 --- a/conan/tools/cmake/cmakedeps/templates/target_data.py +++ b/conan/tools/cmake/cmakedeps/templates/target_data.py @@ -26,7 +26,7 @@ def filename(self): @property def context(self): global_cpp = self._get_global_cpp_cmake() - if not self.build_modules_activated: + if global_cpp and not self.build_modules_activated: global_cpp.build_modules_paths = "" components = self._get_required_components_cpp() @@ -84,6 +84,9 @@ def template(self): ########### VARIABLES ####################################################################### ############################################################################################# set({{ pkg_name }}_PACKAGE_FOLDER{{ config_suffix }} "{{ package_folder }}") + + {% if global_cpp %} + set({{ pkg_name }}_INCLUDE_DIRS{{ config_suffix }} {{ global_cpp.include_paths }}) set({{ pkg_name }}_RES_DIRS{{ config_suffix }} {{ global_cpp.res_paths }}) set({{ pkg_name }}_DEFINITIONS{{ config_suffix }} {{ global_cpp.defines }}) @@ -100,11 +103,10 @@ def template(self): set({{ pkg_name }}_FRAMEWORKS{{ config_suffix }} {{ global_cpp.frameworks }}) set({{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ global_cpp.build_modules_paths }}) set({{ pkg_name }}_BUILD_DIRS{{ config_suffix }} {{ global_cpp.build_paths }}) + {% else %} set({{ pkg_name }}_COMPONENTS{{ config_suffix }} {{ components_names }}) - {%- for comp_variable_name, comp_target_name, cpp in components_cpp %} - ########### COMPONENT {{ comp_target_name }} VARIABLES ############################################# set({{ pkg_name }}_{{ comp_variable_name }}_INCLUDE_DIRS{{ config_suffix }} {{ cpp.include_paths }}) set({{ pkg_name }}_{{ comp_variable_name }}_LIB_DIRS{{ config_suffix }} {{ cpp.lib_paths }}) @@ -128,13 +130,19 @@ def template(self): ) list(APPEND {{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ cpp.build_modules_paths }}) {%- endfor %} + + {%- endif %} """) return ret def _get_global_cpp_cmake(self): - global_cppinfo = self.conanfile.cpp_info.aggregated_components() - pfolder_var_name = "{}_PACKAGE_FOLDER{}".format(self.pkg_name, self.config_suffix) - return _TargetDataContext(global_cppinfo, pfolder_var_name, self.conanfile.package_folder) + sorted_comps = self.conanfile.cpp_info.get_sorted_components() + if sorted_comps: # There are components + return None + else: + pfolder_var_name = "{}_PACKAGE_FOLDER{}".format(self.pkg_name, self.config_suffix) + return _TargetDataContext(self.conanfile.cpp_info, pfolder_var_name, + self.conanfile.package_folder) def _get_required_components_cpp(self): """Returns a list of (component_name, DepsCppCMake)""" diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py index aa5193d7dac..7d0ebdebbb3 100644 --- a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py +++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py @@ -152,7 +152,10 @@ def package_info(self): find_package(openssl CONFIG) crypto_message("hello!") ssl_message("hello!") - root_message("hello!") + # The root build_module is not taken into account because there are components instead + # FIXME: Another alternative could be passing the global_cpp but without aggregating + # the components. + # root_message("hello!") """) client.save({"conanfile.py": consumer, "CMakeLists.txt": cmakelists}) # As we are requiring only "crypto" but it doesn't matter, it is not possible to include @@ -160,5 +163,5 @@ def package_info(self): client.run("create .") assert "SSL MESSAGE:hello!" in client.out assert "CRYPTO MESSAGE:hello!" in client.out - assert "ROOT MESSAGE:hello!" in client.out + assert "ROOT MESSAGE:hello!" not in client.out diff --git a/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py b/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py index bd1aa44a149..a9467294572 100644 --- a/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py +++ b/conans/test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py @@ -107,15 +107,22 @@ def package_info(self): assert """set_property(TARGET hello::say PROPERTY INTERFACE_LINK_LIBRARIES $<$:${hello_hello_say_OBJECTS_RELEASE} ${hello_hello_say_LINK_LIBS_RELEASE}> APPEND)""" in content + # If there are componets, there is not a global cpp so this is not generated assert """set_property(TARGET hello::hello PROPERTY INTERFACE_LINK_LIBRARIES $<$:${hello_OBJECTS_RELEASE} - ${hello_LIBRARIES_TARGETS_RELEASE}> APPEND)""" in content + ${hello_LIBRARIES_TARGETS_RELEASE}> APPEND)""" not in content + # But the global target is linked with the targets from the components + assert "target_link_libraries(hello::hello INTERFACE hello::say)" in content with open(os.path.join(client.current_folder, "hello-release-x86_64-data.cmake")) as f: content = f.read() - assert 'set(hello_OBJECTS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/mycomponent.o")' in content - assert 'set(hello_hello_say_OBJECTS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/mycomponent.o")' in content + # Not global variables + assert 'set(hello_OBJECTS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/mycomponent.o")' \ + not in content + # But component variables + assert 'set(hello_hello_say_OBJECTS_RELEASE "${hello_PACKAGE_FOLDER_RELEASE}/' \ + 'mycomponent.o")' in content def test_cpp_info_component_error_aggregate(): diff --git a/conans/test/unittests/tools/cmake/test_cmakedeps.py b/conans/test/unittests/tools/cmake/test_cmakedeps.py index ec25884ec53..8be95874d93 100644 --- a/conans/test/unittests/tools/cmake/test_cmakedeps.py +++ b/conans/test/unittests/tools/cmake/test_cmakedeps.py @@ -61,8 +61,8 @@ def test_cpp_info_name_cmakedeps_components(): conanfile.settings.arch = "x64" cpp_info = CppInfo("mypkg", "dummy_root_folder1") - cpp_info.set_property("cmake_target_name", "GlobakPkgName1::GlobakPkgName1") - cpp_info.components["mycomp"].set_property("cmake_target_name", "GlobakPkgName1::MySuperPkg1") + cpp_info.set_property("cmake_target_name", "GlobalPkgName1::GlobalPkgName1") + cpp_info.components["mycomp"].set_property("cmake_target_name", "GlobalPkgName1::MySuperPkg1") cpp_info.set_property("cmake_file_name", "ComplexFileName1") conanfile_dep = ConanFile(Mock(), None) @@ -81,11 +81,13 @@ def test_cpp_info_name_cmakedeps_components(): cmakedeps = CMakeDeps(conanfile) files = cmakedeps.content - assert "TARGET GlobakPkgName1::MySuperPkg1" in files["ComplexFileName1-Target-debug.cmake"] + assert "TARGET GlobalPkgName1::MySuperPkg1" in files["ComplexFileName1-Target-debug.cmake"] + # No global variables for the packages assert 'set(OriginalDepName_INCLUDE_DIRS_DEBUG ' \ '"${OriginalDepName_PACKAGE_FOLDER_DEBUG}/include")' \ - in files["ComplexFileName1-debug-x64-data.cmake"] - assert 'set(OriginalDepName_GlobakPkgName1_MySuperPkg1_INCLUDE_DIRS_DEBUG ' \ + not in files["ComplexFileName1-debug-x64-data.cmake"] + # But components + assert 'set(OriginalDepName_GlobalPkgName1_MySuperPkg1_INCLUDE_DIRS_DEBUG ' \ '"${OriginalDepName_PACKAGE_FOLDER_DEBUG}/include")' \ in files["ComplexFileName1-debug-x64-data.cmake"] From e733137d7e6396fc1c21406188b693f963c1b61b Mon Sep 17 00:00:00 2001 From: Luis Date: Tue, 19 Jul 2022 16:17:32 +0200 Subject: [PATCH 2/3] cmake_build_module only from global --- .../cmake/cmakedeps/templates/target_data.py | 16 ++---- .../cmakedeps/test_cmakedeps_build_modules.py | 57 +++++-------------- 2 files changed, 21 insertions(+), 52 deletions(-) diff --git a/conan/tools/cmake/cmakedeps/templates/target_data.py b/conan/tools/cmake/cmakedeps/templates/target_data.py index 8815576bd6e..148e63cead4 100644 --- a/conan/tools/cmake/cmakedeps/templates/target_data.py +++ b/conan/tools/cmake/cmakedeps/templates/target_data.py @@ -49,6 +49,7 @@ def context(self): package_folder = package_folder.replace('\\', '/').replace('$', '\\$').replace('"', '\\"') return {"global_cpp": global_cpp, + "has_components": self.conanfile.cpp_info.has_components, "pkg_name": self.pkg_name, "file_name": self.file_name, "package_folder": package_folder, @@ -84,8 +85,9 @@ def template(self): ########### VARIABLES ####################################################################### ############################################################################################# set({{ pkg_name }}_PACKAGE_FOLDER{{ config_suffix }} "{{ package_folder }}") + set({{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ global_cpp.build_modules_paths }}) - {% if global_cpp %} + {% if not has_components %} set({{ pkg_name }}_INCLUDE_DIRS{{ config_suffix }} {{ global_cpp.include_paths }}) set({{ pkg_name }}_RES_DIRS{{ config_suffix }} {{ global_cpp.res_paths }}) @@ -101,7 +103,6 @@ def template(self): set({{ pkg_name }}_SYSTEM_LIBS{{ config_suffix }} {{ global_cpp.system_libs }}) set({{ pkg_name }}_FRAMEWORK_DIRS{{ config_suffix }} {{ global_cpp.framework_paths }}) set({{ pkg_name }}_FRAMEWORKS{{ config_suffix }} {{ global_cpp.frameworks }}) - set({{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ global_cpp.build_modules_paths }}) set({{ pkg_name }}_BUILD_DIRS{{ config_suffix }} {{ global_cpp.build_paths }}) {% else %} @@ -128,7 +129,6 @@ def template(self): $<$,MODULE_LIBRARY>{{ ':${' }}{{ pkg_name }}_{{ comp_variable_name }}_SHARED_LINK_FLAGS{{ config_suffix }}}> $<$,EXECUTABLE>{{ ':${' }}{{ pkg_name }}_{{ comp_variable_name }}_EXE_LINK_FLAGS{{ config_suffix }}}> ) - list(APPEND {{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ cpp.build_modules_paths }}) {%- endfor %} {%- endif %} @@ -136,13 +136,9 @@ def template(self): return ret def _get_global_cpp_cmake(self): - sorted_comps = self.conanfile.cpp_info.get_sorted_components() - if sorted_comps: # There are components - return None - else: - pfolder_var_name = "{}_PACKAGE_FOLDER{}".format(self.pkg_name, self.config_suffix) - return _TargetDataContext(self.conanfile.cpp_info, pfolder_var_name, - self.conanfile.package_folder) + pfolder_var_name = "{}_PACKAGE_FOLDER{}".format(self.pkg_name, self.config_suffix) + return _TargetDataContext(self.conanfile.cpp_info, pfolder_var_name, + self.conanfile.package_folder) def _get_required_components_cpp(self): """Returns a list of (component_name, DepsCppCMake)""" diff --git a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py index 7d0ebdebbb3..3566bfaded3 100644 --- a/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py +++ b/conans/test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py @@ -6,8 +6,7 @@ @pytest.mark.tool_cmake -@pytest.mark.parametrize("use_components", [False, True]) -def test_build_modules_alias_target(use_components): +def test_build_modules_alias_target(): client = TestClient() conanfile = textwrap.dedent(""" import os @@ -24,21 +23,13 @@ def package(self): def package_info(self): module = os.path.join("share", "cmake", "target-alias.cmake") - {} + self.cpp_info.set_property("cmake_build_modules", [module]) """) - if use_components: - info = """ - self.cpp_info.components["comp"].set_property("cmake_build_modules", [module]) - """ - else: - info = """ - self.cpp_info.set_property("cmake_build_modules", [module]) - """ + target_alias = textwrap.dedent(""" add_library(otherhello INTERFACE IMPORTED) - target_link_libraries(otherhello INTERFACE {target_name}) - """).format(target_name="namespace::comp" if use_components else "hello::hello") - conanfile = conanfile.format(info) + target_link_libraries(otherhello INTERFACE hello::hello) + """) client.save({"conanfile.py": conanfile, "target-alias.cmake": target_alias}) client.run("create .") @@ -66,20 +57,13 @@ def build(self): """) client.save({"conanfile.py": consumer, "CMakeLists.txt": cmakelists}) client.run("create .") - if use_components: - assert "otherhello link libraries: namespace::comp" in client.out - else: - assert "otherhello link libraries: hello::hello" in client.out + assert "otherhello link libraries: hello::hello" in client.out @pytest.mark.tool_cmake -def test_build_modules_components_selection_is_not_possible(): +def test_build_modules_components_is_not_possible(): """ - If openssl declares different cmake_build_modules on ssl and crypto, in the consumer both - are included even if the cpp_info of the consumer declares: - def package_info(self): - self.cpp_info.requires = ["openssl::crypto"] - Because that information is defined later, not at "generate" time (building time). + The "cmake_build_module" property declared in the components is useless """ client = TestClient() conanfile = textwrap.dedent(""" @@ -90,15 +74,12 @@ class Conan(ConanFile): name = "openssl" version = "1.0" settings = "os", "arch", "compiler", "build_type" - exports_sources = ["ssl.cmake", "crypto.cmake", "root.cmake"] + exports_sources = ["crypto.cmake", "root.cmake"] def package(self): self.copy("*.cmake", dst="share/cmake") def package_info(self): - ssl_module = os.path.join("share", "cmake", "ssl.cmake") - self.cpp_info.components["ssl"].set_property("cmake_build_modules", [ssl_module]) - crypto_module = os.path.join("share", "cmake", "crypto.cmake") self.cpp_info.components["crypto"].set_property("cmake_build_modules", [crypto_module]) @@ -106,11 +87,6 @@ def package_info(self): self.cpp_info.set_property("cmake_build_modules", [root_module]) """) - ssl_cmake = textwrap.dedent(""" - function(ssl_message MESSAGE_OUTPUT) - message("SSL MESSAGE:${ARGV${0}}") - endfunction() - """) crypto_cmake = textwrap.dedent(""" function(crypto_message MESSAGE_OUTPUT) message("CRYPTO MESSAGE:${ARGV${0}}") @@ -122,7 +98,6 @@ def package_info(self): endfunction() """) client.save({"conanfile.py": conanfile, - "ssl.cmake": ssl_cmake, "crypto.cmake": crypto_cmake, "root.cmake": root_cmake}) client.run("create .") @@ -151,17 +126,15 @@ def package_info(self): project(test) find_package(openssl CONFIG) crypto_message("hello!") - ssl_message("hello!") - # The root build_module is not taken into account because there are components instead - # FIXME: Another alternative could be passing the global_cpp but without aggregating - # the components. - # root_message("hello!") + root_message("hello!") """) client.save({"conanfile.py": consumer, "CMakeLists.txt": cmakelists}) # As we are requiring only "crypto" but it doesn't matter, it is not possible to include # only crypto build_modules - client.run("create .") - assert "SSL MESSAGE:hello!" in client.out - assert "CRYPTO MESSAGE:hello!" in client.out + client.run("create .", assert_error=True) + assert 'Unknown CMake command "crypto_message"' in client.out + + # Comment the function call + client.save({"CMakeLists.txt": cmakelists.replace("crypto", "#crypto")}) assert "ROOT MESSAGE:hello!" not in client.out From 183d0ab5d4653314fff622eb1a43a011ad47a6fe Mon Sep 17 00:00:00 2001 From: Luis Date: Wed, 20 Jul 2022 10:02:24 +0200 Subject: [PATCH 3/3] fix if --- conan/tools/cmake/cmakedeps/templates/target_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conan/tools/cmake/cmakedeps/templates/target_data.py b/conan/tools/cmake/cmakedeps/templates/target_data.py index 148e63cead4..f3c2671b40a 100644 --- a/conan/tools/cmake/cmakedeps/templates/target_data.py +++ b/conan/tools/cmake/cmakedeps/templates/target_data.py @@ -26,7 +26,7 @@ def filename(self): @property def context(self): global_cpp = self._get_global_cpp_cmake() - if global_cpp and not self.build_modules_activated: + if not self.build_modules_activated: global_cpp.build_modules_paths = "" components = self._get_required_components_cpp()