Repository: conan-io/conan
Pull request #16724 (2024-07-24 16:58:03)

fix runtime_deployer with run=False
Changelog: Fix: Avoid ``runtime_deployer`` to deploy dependencies with ``run=False`` trait.
Docs: Omit

Close https://github.com/conan-io/conan/issues/16712



Patch:
diff --git a/conan/internal/deploy.py b/conan/internal/deploy.py
index d5f04693d..bf41f920c 100644
--- a/conan/internal/deploy.py
+++ b/conan/internal/deploy.py
@@ -40,7 +40,10 @@ def _find_deployer(d, cache_deploy_folder):
 
 
 def do_deploys(conan_api, graph, deploy, deploy_package, deploy_folder):
-    mkdir(deploy_folder)
+    try:
+        mkdir(deploy_folder)
+    except Exception as e:
+        raise ConanException(f"Deployer folder cannot be created '{deploy_folder}':\n{e}")
     # handle the recipe deploy()
     if deploy_package:
         # Similar processing as BuildMode class
@@ -100,7 +103,9 @@ def runtime_deploy(graph, output_folder):
                    "Please give feedback at https://github.com/conan-io/conan/issues")
     mkdir(output_folder)
     symlinks = conanfile.conf.get("tools.deployer:symlinks", check_type=bool, default=True)
-    for _, dep in conanfile.dependencies.host.items():
+    for req, dep in conanfile.dependencies.host.items():
+        if not req.run:  # Avoid deploying unused binaries at runtime
+            continue
         if dep.package_folder is None:
             output.warning(f"{dep.ref} does not have any package folder, skipping binary")
             continue


Test patch:
diff --git a/test/functional/command/test_install_deploy.py b/test/functional/command/test_install_deploy.py
index 1967e4b48..b4bbeb73e 100644
--- a/test/functional/command/test_install_deploy.py
+++ b/test/functional/command/test_install_deploy.py
@@ -437,6 +437,18 @@ def test_not_deploy_absolute_paths():
     assert f'export MYPATH="{some_abs_path}/mypath"' in env
 
 
+def test_deploy_incorrect_folder():
+    # https://github.com/conan-io/cmake-conan/issues/658
+    c = TestClient()
+    c.save({"conanfile.txt": ""})
+    c.run('install . --deployer=full_deploy --deployer-folder="mydep fold"')
+    assert os.path.exists(os.path.join(c.current_folder, "mydep fold"))
+    if platform.system() == "Windows":  # This only fails in Windows
+        c.run(r'install . --deployer=full_deploy --deployer-folder="\"mydep fold\""',
+              assert_error=True)
+        assert "ERROR: Deployer folder cannot be created" in c.out
+
+
 class TestRuntimeDeployer:
     def test_runtime_deploy(self):
         c = TestClient()
@@ -444,6 +456,7 @@ class TestRuntimeDeployer:
            from conan import ConanFile
            from conan.tools.files import copy
            class Pkg(ConanFile):
+               package_type = "shared-library"
                def package(self):
                    copy(self, "*.so", src=self.build_folder, dst=self.package_folder)
                    copy(self, "*.dll", src=self.build_folder, dst=self.package_folder)
@@ -461,6 +474,25 @@ class TestRuntimeDeployer:
         expected = sorted(["pkga.so", "pkgb.so", "pkga.dll"])
         assert sorted(os.listdir(os.path.join(c.current_folder, "myruntime"))) == expected
 
+    def test_runtime_not_deploy(self):
+        # https://github.com/conan-io/conan/issues/16712
+        # If no run=False (no package-type), then no runtime is deployed
+        c = TestClient()
+        conanfile = textwrap.dedent("""
+           from conan import ConanFile
+           from conan.tools.files import copy
+           class Pkg(ConanFile):
+               def package(self):
+                   copy(self, "*.so", src=self.build_folder, dst=self.package_folder)
+                   copy(self, "*.dll", src=self.build_folder, dst=self.package_folder)
+           """)
+        c.save({"pkga/conanfile.py": conanfile,
+                "pkga/lib/pkga.so": "",
+                "pkga/bin/pkga.dll": ""})
+        c.run("export-pkg pkga --name=pkga --version=1.0")
+        c.run("install --requires=pkga/1.0 --deployer=runtime_deploy --deployer-folder=myruntime")
+        assert os.listdir(os.path.join(c.current_folder, "myruntime")) == []
+
     def test_runtime_deploy_components(self):
         c = TestClient()
         conanfile = textwrap.dedent("""
@@ -468,6 +500,7 @@ class TestRuntimeDeployer:
             from conan import ConanFile
             from conan.tools.files import copy
             class Pkg(ConanFile):
+               package_type = "shared-library"
                def package(self):
                    copy(self, "*.so", src=self.build_folder,
                         dst=os.path.join(self.package_folder, "a"))