Repository: conan-io/conan
Pull request #17917 (2025-03-09 22:32:52)

Fix usage of cmake_set_interface_link_directories property
Changelog: Fix: the ``cmake_set_interface_link_directories`` property is not really necessary at all in ``CMakeDeps`` and it becomes invalid in ``CMakeConfigDeps`` as it will require full ``package_info()`` definition.
Docs: TODO

Close https://github.com/conan-io/conan/issues/15611


Patch:
diff --git a/conan/tools/cmake/cmakedeps/cmakedeps.py b/conan/tools/cmake/cmakedeps/cmakedeps.py
index d8d607778..d65ad659f 100644
--- a/conan/tools/cmake/cmakedeps/cmakedeps.py
+++ b/conan/tools/cmake/cmakedeps/cmakedeps.py
@@ -137,7 +137,7 @@ class CMakeDeps(object):
         Using this method you can overwrite the :ref:`property<CMakeDeps Properties>` values set by
         the Conan recipes from the consumer. This can be done for `cmake_file_name`, `cmake_target_name`,
         `cmake_find_mode`, `cmake_module_file_name`, `cmake_module_target_name`, `cmake_additional_variables_prefixes`,
-        `cmake_config_version_compat`, `system_package_version`, `cmake_set_interface_link_directories`,
+        `cmake_config_version_compat`, `system_package_version`,
         `cmake_build_modules`, `nosoname`, and `cmake_target_aliases`.
 
         :param dep: Name of the dependency to set the :ref:`property<CMakeDeps Properties>`. For
diff --git a/conan/tools/cmake/cmakedeps/templates/target_configuration.py b/conan/tools/cmake/cmakedeps/templates/target_configuration.py
index 747b2bf01..d31cb1dc1 100644
--- a/conan/tools/cmake/cmakedeps/templates/target_configuration.py
+++ b/conan/tools/cmake/cmakedeps/templates/target_configuration.py
@@ -29,6 +29,11 @@ class TargetConfigurationTemplate(CMakeDepsFileTemplate):
         is_win = self.conanfile.settings.get_safe("os") == "Windows"
         auto_link = self.cmakedeps.get_property("cmake_set_interface_link_directories",
                                                 self.conanfile, check_type=bool)
+        if auto_link:
+            out = self.cmakedeps._conanfile.output # noqa
+            out.warning("CMakeDeps: cmake_set_interface_link_directories is legacy, not necessary",
+                        warn_tag="deprecated")
+
         return {"pkg_name": self.pkg_name,
                 "root_target_name": self.root_target_name,
                 "config_suffix": self.config_suffix,
@@ -119,16 +124,6 @@ class TargetConfigurationTemplate(CMakeDepsFileTemplate):
             set_property(TARGET {{root_target_name}}
                          APPEND PROPERTY INTERFACE_COMPILE_OPTIONS
                          $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'COMPILE_OPTIONS', config_suffix) }}>)
-
-            {%- if set_interface_link_directories %}
-
-            # This is only used for '#pragma comment(lib, "foo")' (automatic link)
-            set_property(TARGET {{root_target_name}}
-                         APPEND PROPERTY INTERFACE_LINK_DIRECTORIES
-                         $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'LIB_DIRS', config_suffix) }}>)
-            {%- endif %}
-
-
         {%- else %}
 
         ########## COMPONENTS TARGET PROPERTIES {{ configuration }} ########################################
@@ -188,19 +183,12 @@ class TargetConfigurationTemplate(CMakeDepsFileTemplate):
                              $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'LINKER_FLAGS', config_suffix) }}>)
                 set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
                              $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'INCLUDE_DIRS', config_suffix) }}>)
-                set_property(TARGET {{comp_target_name }} APPEND PROPERTY INTERFACE_LINK_DIRECTORIES
+                set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_LINK_DIRECTORIES
                              $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'LIB_DIRS', config_suffix) }}>)
                 set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS
                              $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'COMPILE_DEFINITIONS', config_suffix) }}>)
                 set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_COMPILE_OPTIONS
                              $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'COMPILE_OPTIONS', config_suffix) }}>)
-
-                {%- if set_interface_link_directories %}
-                # This is only used for '#pragma comment(lib, "foo")' (automatic link)
-                set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_LINK_DIRECTORIES
-                             $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'LIB_DIRS', config_suffix) }}>)
-
-                {%- endif %}
             {%endfor %}
 
 
diff --git a/conan/tools/cmake/cmakedeps2/target_configuration.py b/conan/tools/cmake/cmakedeps2/target_configuration.py
index 9af4ea614..e85df76fd 100644
--- a/conan/tools/cmake/cmakedeps2/target_configuration.py
+++ b/conan/tools/cmake/cmakedeps2/target_configuration.py
@@ -20,6 +20,13 @@ class TargetConfigurationTemplate2:
         self._require = require
 
     def content(self):
+        auto_link = self._cmakedeps.get_property("cmake_set_interface_link_directories",
+                                                 self._conanfile, check_type=bool)
+        if auto_link:
+            out = self._cmakedeps._conanfile.output  # noqa
+            out.warning("CMakeConfigDeps: cmake_set_interface_link_directories deprecated and "
+                        "invalid. The package 'package_info()' must correctly define the (CPS) "
+                        "information", warn_tag="deprecated")
         t = Template(self._template, trim_blocks=True, lstrip_blocks=True,
                      undefined=jinja2.StrictUndefined)
         return t.render(self._context)


Test patch:
diff --git a/test/functional/toolchains/cmake/test_cmake_toolchain.py b/test/functional/toolchains/cmake/test_cmake_toolchain.py
index ac0606062..14ed165c6 100644
--- a/test/functional/toolchains/cmake/test_cmake_toolchain.py
+++ b/test/functional/toolchains/cmake/test_cmake_toolchain.py
@@ -480,101 +480,6 @@ def test_cmake_toolchain_definitions_complex_strings():
     assert 'answer_debug=21' in client.out
 
 
-class TestAutoLinkPragma:
-    # TODO: This is a CMakeDeps test, not a CMakeToolchain test, move it to the right place
-
-    test_cf = textwrap.dedent("""
-        import os
-
-        from conan import ConanFile
-        from conan.tools.cmake import CMake, cmake_layout, CMakeDeps
-        from conan.tools.build import cross_building
-
-
-        class HelloTestConan(ConanFile):
-            settings = "os", "compiler", "build_type", "arch"
-            generators = "CMakeToolchain", "VirtualBuildEnv", "VirtualRunEnv"
-            apply_env = False
-            test_type = "explicit"
-
-            def generate(self):
-                deps = CMakeDeps(self)
-                deps.generate()
-
-            def requirements(self):
-                self.requires(self.tested_reference_str)
-
-            def build(self):
-                cmake = CMake(self)
-                cmake.configure()
-                cmake.build()
-
-            def layout(self):
-                cmake_layout(self)
-
-            def test(self):
-                if not cross_building(self):
-                    cmd = os.path.join(self.cpp.build.bindirs[0], "example")
-                    self.run(cmd, env="conanrun")
-        """)
-
-    @pytest.mark.skipif(platform.system() != "Windows", reason="Requires Visual Studio")
-    @pytest.mark.tool("cmake")
-    def test_autolink_pragma_components(self):
-        """https://github.com/conan-io/conan/issues/10837
-
-        NOTE: At the moment the property cmake_set_interface_link_directories is only read at the
-        global cppinfo, not in the components"""
-
-        client = TestClient()
-        client.run("new cmake_lib -d name=hello -d version=1.0")
-        cf = client.load("conanfile.py")
-        cf = cf.replace('self.cpp_info.libs = ["hello"]', """
-            self.cpp_info.components['my_component'].includedirs.append('include')
-            self.cpp_info.components['my_component'].libdirs.append('lib')
-            self.cpp_info.components['my_component'].libs = []
-            self.cpp_info.set_property("cmake_set_interface_link_directories", True)
-        """)
-        hello_h = client.load("include/hello.h")
-        hello_h = hello_h.replace("#define HELLO_EXPORT __declspec(dllexport)",
-                                  '#define HELLO_EXPORT __declspec(dllexport)\n'
-                                  '#pragma comment(lib, "hello")')
-
-        test_cmakelist = client.load("test_package/CMakeLists.txt")
-        test_cmakelist = test_cmakelist.replace("target_link_libraries(example hello::hello)",
-                                                "target_link_libraries(example hello::my_component)")
-        client.save({"conanfile.py": cf,
-                     "include/hello.h": hello_h,
-                     "test_package/CMakeLists.txt": test_cmakelist,
-                     "test_package/conanfile.py": self.test_cf})
-
-        client.run("create .")
-
-    @pytest.mark.skipif(platform.system() != "Windows", reason="Requires Visual Studio")
-    @pytest.mark.tool("cmake")
-    def test_autolink_pragma_without_components(self):
-        """https://github.com/conan-io/conan/issues/10837"""
-        client = TestClient()
-        client.run("new cmake_lib -d name=hello -d version=1.0")
-        cf = client.load("conanfile.py")
-        cf = cf.replace('self.cpp_info.libs = ["hello"]', """
-            self.cpp_info.includedirs.append('include')
-            self.cpp_info.libdirs.append('lib')
-            self.cpp_info.libs = []
-            self.cpp_info.set_property("cmake_set_interface_link_directories", True)
-        """)
-        hello_h = client.load("include/hello.h")
-        hello_h = hello_h.replace("#define HELLO_EXPORT __declspec(dllexport)",
-                                  '#define HELLO_EXPORT __declspec(dllexport)\n'
-                                  '#pragma comment(lib, "hello")')
-
-        client.save({"conanfile.py": cf,
-                     "include/hello.h": hello_h,
-                     "test_package/conanfile.py": self.test_cf})
-
-        client.run("create .")
-
-
 @pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows")
 def test_cmake_toolchain_runtime_types():
     # everything works with the default cmake_minimum_required version 3.15 in the template
diff --git a/test/integration/toolchains/cmake/cmakedeps2/test_cmakedeps.py b/test/integration/toolchains/cmake/cmakedeps2/test_cmakedeps.py
index 76f0aee4b..e54bb2a61 100644
--- a/test/integration/toolchains/cmake/cmakedeps2/test_cmakedeps.py
+++ b/test/integration/toolchains/cmake/cmakedeps2/test_cmakedeps.py
@@ -178,3 +178,23 @@ def test_system_wrappers():
     cmake = c.load("lib-Targets-release.cmake")
     assert "add_library(lib::lib INTERFACE IMPORTED)" in cmake
     assert "target_link_libraries(lib::lib INTERFACE my_system_cool_lib)" in cmake
+
+
+def test_autolink_pragma():
+    """https://github.com/conan-io/conan/issues/10837"""
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        class Pkg(ConanFile):
+            def package_info(self):
+                self.cpp_info.set_property("cmake_set_interface_link_directories", True)
+        """)
+    c.save({"conanfile.py": conanfile,
+            "test_package/conanfile.py": GenConanfile().with_test("pass")
+                                                       .with_settings("build_type")
+                                                       .with_generator("CMakeDeps")})
+    c.run("create . --name=pkg --version=0.1")
+    assert "CMakeDeps: cmake_set_interface_link_directories is legacy, not necessary" in c.out
+    c.run("create . --name=pkg --version=0.1 -c tools.cmake.cmakedeps:new=will_break_next")
+    assert "CMakeConfigDeps: cmake_set_interface_link_directories deprecated and invalid. " \
+           "The package 'package_info()' must correctly define the (CPS) information" in c.out