Repository: conan-io/conan
Pull request #12762 (2022-12-21 20:23:14)

Add cmake install component support #10359
Changelog: (Feature): Add the ability to provide a `--component` argument with the `cmake.install` function. Related issue #10359
Docs: https://github.com/conan-io/docs/pull/XXXX

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [x] I've followed the PEP8 style guides for Python code.
- [ ] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one. 

<sup>**Note:** By default this PR will skip the slower tests and will use a limited set of python versions. Check [here](https://github.com/conan-io/conan/blob/develop/.github/PR_INCREASE_TESTING.md) how to increase the testing level by writing some tags in the current PR body text.</sup>


CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/conan-io/conan?pullRequest=12762) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/conan-io/conan?pullRequest=12762) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/conan-io/conan?pullRequest=12762) it.</sub>

Patch:
diff --git a/conan/tools/cmake/cmake.py b/conan/tools/cmake/cmake.py
index 63cb6a1a1..9b8e1a0f0 100644
--- a/conan/tools/cmake/cmake.py
+++ b/conan/tools/cmake/cmake.py
@@ -132,7 +132,7 @@ class CMake(object):
     def build(self, build_type=None, target=None, cli_args=None, build_tool_args=None):
         self._build(build_type, target, cli_args, build_tool_args)
 
-    def install(self, build_type=None):
+    def install(self, build_type=None, component=None):
         mkdir(self._conanfile, self._conanfile.package_folder)
 
         bt = build_type or self._conanfile.settings.get_safe("build_type")
@@ -144,6 +144,8 @@ class CMake(object):
         pkg_folder = '"{}"'.format(self._conanfile.package_folder.replace("\\", "/"))
         build_folder = '"{}"'.format(self._conanfile.build_folder)
         arg_list = ["--install", build_folder, build_config, "--prefix", pkg_folder]
+        if component:
+            arg_list.extend(["--component", component])
         arg_list = " ".join(filter(None, arg_list))
         command = "%s %s" % (self._cmake_program, arg_list)
         self._conanfile.output.info("CMake command: %s" % command)
diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py
index e94c59978..a4c2dbb53 100644
--- a/conans/client/graph/graph_binaries.py
+++ b/conans/client/graph/graph_binaries.py
@@ -193,6 +193,7 @@ class GraphBinariesAnalyzer(object):
             if node.package_id != locked.package_id:  # It was a compatible package
                 # https://github.com/conan-io/conan/issues/9002
                 # We need to iterate to search the compatible combination
+                self._compatibility.compatibles(node.conanfile)
                 for compatible_package in node.conanfile.compatible_packages:
                     comp_package_id = compatible_package.package_id()
                     if comp_package_id == locked.package_id:


Test patch:
diff --git a/conans/test/integration/graph_lock/test_compatibility.py b/conans/test/integration/graph_lock/test_compatibility.py
new file mode 100644
index 000000000..95271e00f
--- /dev/null
+++ b/conans/test/integration/graph_lock/test_compatibility.py
@@ -0,0 +1,38 @@
+import textwrap
+
+from conans.test.assets.genconanfile import GenConanfile
+from conans.test.utils.tools import TestClient
+
+
+def test_lockfile_compatibility():
+    c = TestClient()
+    conanfile = textwrap.dedent("""
+        from conan import ConanFile
+        class Pkg(ConanFile):
+            name = "pkg"
+            version = "1.0"
+            settings = "build_type"
+            def compatibility(self):
+                if self.settings.build_type == "Release":
+                   return [ {"settings": [("build_type", "None")]}, ]
+            """)
+    c.save({"conanfile.py": conanfile,
+            "profile": ""})
+    c.run("create . -pr=profile")
+    c.save({"conanfile.py": GenConanfile().with_requires("pkg/1.0")})
+    c.run("install .")
+    assert "pkg/1.0: Main binary package '4024617540c4f240a6a5e8911b0de9ef38a11a72' missing. " \
+           "Using compatible package '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9'" in c.out
+
+    c.run("lock create conanfile.py --base")
+    assert "pkg/1.0: Main binary package '4024617540c4f240a6a5e8911b0de9ef38a11a72' missing. " \
+           "Using compatible package '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9'" in c.out
+
+    c.run("lock create conanfile.py --lockfile=conan.lock")
+    conan_lock = c.load("conan.lock")
+    assert '"package_id": "5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9"' in conan_lock
+    assert "pkg/1.0: Main binary package '4024617540c4f240a6a5e8911b0de9ef38a11a72' missing. " \
+           "Using compatible package '5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9'" in c.out
+
+    c.run("install . --lockfile=conan.lock")
+    assert "pkg/1.0:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 - Cache" in c.out
diff --git a/conans/test/unittests/tools/cmake/test_cmake_install.py b/conans/test/unittests/tools/cmake/test_cmake_install.py
new file mode 100644
index 000000000..273c38835
--- /dev/null
+++ b/conans/test/unittests/tools/cmake/test_cmake_install.py
@@ -0,0 +1,39 @@
+import platform
+import pytest
+
+from conan.tools.cmake import CMake
+from conan.tools.cmake.presets import write_cmake_presets
+from conans.client.conf import get_default_settings_yml
+from conans.model.conf import Conf
+from conans.model.settings import Settings
+from conans.test.utils.mocks import ConanFileMock
+from conans.test.utils.test_files import temp_folder
+
+
+def test_run_install_component():
+    """
+    Testing that the proper component is installed.
+    Issue related: https://github.com/conan-io/conan/issues/10359
+    """
+    # Load some generic windows settings
+    settings = Settings.loads(get_default_settings_yml())
+    settings.os = "Windows"
+    settings.arch = "x86"
+    settings.build_type = "Release"
+    settings.compiler = "Visual Studio"
+    settings.compiler.runtime = "MDd"
+    settings.compiler.version = "14"
+
+    conanfile = ConanFileMock()
+    conanfile.conf = Conf()
+    conanfile.folders.generators = "."
+    conanfile.folders.set_base_generators(temp_folder())
+    conanfile.settings = settings
+    conanfile.folders.set_base_package(temp_folder())
+
+    # Choose generator to match generic setttings
+    write_cmake_presets(conanfile, "toolchain", "Visual Studio 14 2015", {})
+    cmake = CMake(conanfile)
+    cmake.install(component="foo")
+
+    assert "--component foo" in conanfile.command