Repository: conan-io/conan

Issue:
Warning when using cmake.install() for packaging
To help us debug your issue please explain:

- [x] I've read the [CONTRIBUTING guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [x] I've specified the Conan version, operating system version and any tool that can be relevant.
- [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.

I'm using conan version 1.4.4, running on Windows 10
I have a simple conanfile.py, which contains mostly:

    def configure_cmake(self):
        cmake = CMake(self)
        cmake.configure()
        return cmake

    def build(self):
        cmake = self.configure_cmake()
        cmake.build()

    def package(self):
        cmake = self.configure_cmake()
        cmake.install()

Note that cmake.install is used to copy files into the package folder. This method is documented at https://docs.conan.io/en/latest/reference/build_helpers/cmake.html.

I invoke conan like this:

conan export conanfile.py MyUser/MyChannel
conan install MyPackage/MyVersion@MyUser/MyChannel --build

I get a warning 
MyPackage/MyVersion@MyUser/MyChannel: WARN: No files copied from build folder!

However, the package folder does actually contain my files. The warning is incorrect. Is there some way for me to suppress it? I generally don't allow any warnings or errors in my build process.



Discussion:
Agree, this should be improved.

Maybe instead of capturing the files copied (by self.copy), it would be enough to report over the final package created. That would be good for all cases.
Usually we copy the license file `self.copy("LICENSE", "licenses")`, but
for internal projects, it makes sense. We could check if package folder was
populated instead of monitor self.copy method.

On Thu, Jan 31, 2019 at 10:23 PM EricBackus <notifications@github.com>
wrote:

> To help us debug your issue please explain:
>
>    - I've read the CONTRIBUTING guide
>    <https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md>
>    .
>    - I've specified the Conan version, operating system version and any
>    tool that can be relevant.
>    - I've explained the steps to reproduce the error or the
>    motivation/use case of the question/suggestion.
>
> I'm using conan version 1.4.4, running on Windows 10
> I have a simple conanfile.py, which contains mostly:
>
> def configure_cmake(self):
>     cmake = CMake(self)
>     cmake.configure()
>     return cmake
>
> def build(self):
>     cmake = self.configure_cmake()
>     cmake.build()
>
> def package(self):
>     cmake = self.configure_cmake()
>     cmake.install()
>
> Note that cmake.install is used to copy files into the package folder.
> This method is documented at
> https://docs.conan.io/en/latest/reference/build_helpers/cmake.html.
>
> I invoke conan like this:
>
> conan export conanfile.py MyUser/MyChannel
> conan install MyPackage/MyVersion@MyUser/MyChannel --build
>
> I get a warning
> MyPackage/MyVersion@MyUser/MyChannel: WARN: No files copied from build
> folder!
>
> However, the package folder does actually contain my files. The warning is
> incorrect. Is there some way for me to suppress it? I generally don't allow
> any warnings or errors in my build process.
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/conan-io/conan/issues/4438>, or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AEpQHZ_cMcaMExMp3h2C-CTCrecxCZhCks5vI4j7gaJpZM4ada4A>
> .
>


-- 
Cordialmente,

Uilian Ries
<uilianries@gmail.com>


Resolving patch:
diff --git a/conans/client/file_copier.py b/conans/client/file_copier.py
--- a/conans/client/file_copier.py
+++ b/conans/client/file_copier.py
@@ -6,7 +6,7 @@
 from conans.util.files import mkdir, walk
 
 
-def report_copied_files(copied, output):
+def report_copied_files(copied, output, message_suffix="Copied"):
     ext_files = defaultdict(list)
     for f in copied:
         _, ext = os.path.splitext(f)
@@ -19,9 +19,9 @@ def report_copied_files(copied, output):
         files_str = (", ".join(files)) if len(files) < 5 else ""
         file_or_files = "file" if len(files) == 1 else "files"
         if not ext:
-            output.info("Copied %d %s: %s" % (len(files), file_or_files, files_str))
+            output.info("%s %d %s: %s" % (message_suffix, len(files), file_or_files, files_str))
         else:
-            output.info("Copied %d '%s' %s: %s" % (len(files), ext, file_or_files, files_str))
+            output.info("%s %d '%s' %s: %s" % (message_suffix, len(files), ext, file_or_files, files_str))
     return True
 
 
diff --git a/conans/client/packager.py b/conans/client/packager.py
--- a/conans/client/packager.py
+++ b/conans/client/packager.py
@@ -2,7 +2,7 @@
 import shutil
 
 from conans.client import tools
-from conans.client.file_copier import FileCopier
+from conans.client.file_copier import FileCopier, report_copied_files
 from conans.client.output import ScopedOutput
 from conans.errors import (ConanException, ConanExceptionInUserConanfileMethod,
                            conanfile_exception_formatter)
@@ -25,13 +25,12 @@ def export_pkg(conanfile, package_id, src_package_folder, package_folder, hook_m
     copier = FileCopier(src_package_folder, package_folder)
     copier("*", symlinks=True)
 
-    copy_done = copier.report(output)
-    if not copy_done:
-        output.warn("No files copied from package folder!")
-
     save(os.path.join(package_folder, CONANINFO), conanfile.info.dumps())
     digest = FileTreeManifest.create(package_folder)
     digest.save(package_folder)
+
+    _report_files_from_manifest(output, package_folder)
+
     output.success("Package '%s' created" % package_id)
     conanfile.package_folder = package_folder
     hook_manager.execute("post_package", conanfile=conanfile, conanfile_path=conanfile_path,
@@ -45,7 +44,6 @@ def create_package(conanfile, package_id, source_folder, build_folder, package_f
     package folder
     """
     mkdir(package_folder)
-
     output = conanfile.output
     # Make the copy of all the patterns
     output.info("Generating the package")
@@ -63,25 +61,16 @@ def create_package(conanfile, package_id, source_folder, build_folder, package_f
         package_output = ScopedOutput("%s package()" % output.scope, output)
         output.highlight("Calling package()")
 
-        def recipe_has(attribute):
-            return attribute in conanfile.__class__.__dict__
-
         if source_folder != build_folder:
             conanfile.copy = FileCopier(source_folder, package_folder, build_folder)
             with conanfile_exception_formatter(str(conanfile), "package"):
                 with tools.chdir(source_folder):
                     conanfile.package()
-            copy_done = conanfile.copy.report(package_output)
-            if not copy_done and recipe_has("package"):
-                output.warn("No files copied from source folder!")
 
         conanfile.copy = FileCopier(build_folder, package_folder)
         with tools.chdir(build_folder):
             with conanfile_exception_formatter(str(conanfile), "package"):
                 conanfile.package()
-        copy_done = conanfile.copy.report(package_output)
-        if not copy_done and recipe_has("build") and recipe_has("package"):
-            output.warn("No files copied from build folder!")
     except Exception as e:
         if not local:
             os.chdir(build_folder)
@@ -96,6 +85,7 @@ def recipe_has(attribute):
         raise ConanException(e)
 
     _create_aux_files(install_folder, package_folder, conanfile, copy_info)
+    _report_files_from_manifest(package_output, package_folder)
     package_id = package_id or os.path.basename(package_folder)
     output.success("Package '%s' created" % package_id)
     hook_manager.execute("post_package", conanfile=conanfile, conanfile_path=conanfile_path,
@@ -120,3 +110,15 @@ def _create_aux_files(install_folder, package_folder, conanfile, copy_info):
     # Create the digest for the package
     digest = FileTreeManifest.create(package_folder)
     digest.save(package_folder)
+
+
+def _report_files_from_manifest(output, package_folder):
+    digest = FileTreeManifest.load(package_folder)
+    copied_files = list(digest.files())
+    copied_files.remove(CONANINFO)
+
+    if not copied_files:
+        output.warn("No files in this package!")
+        return
+
+    report_copied_files(copied_files, output, message_suffix="Packaged")


Test patch:
diff --git a/conans/test/functional/command/create_test.py b/conans/test/functional/command/create_test.py
--- a/conans/test/functional/command/create_test.py
+++ b/conans/test/functional/command/create_test.py
@@ -95,7 +95,7 @@ def test(self):
         self.assertIn("Pkg/0.1@lasote/testing: mysource!!", client.out)
         self.assertIn("Pkg/0.1@lasote/testing: mybuild!!", client.out)
         self.assertIn("Pkg/0.1@lasote/testing: mypackage!!", client.out)
-        self.assertIn("Pkg/0.1@lasote/testing package(): Copied 1 '.h' file: header.h", client.out)
+        self.assertIn("Pkg/0.1@lasote/testing package(): Packaged 1 '.h' file: header.h", client.out)
         # keep the source
         client.save({"conanfile.py": conanfile + " "})
         client.run("create . Pkg/0.1@lasote/testing --keep-source")
@@ -103,7 +103,7 @@ def test(self):
         self.assertNotIn("Pkg/0.1@lasote/testing: mysource!!", client.out)
         self.assertIn("Pkg/0.1@lasote/testing: mybuild!!", client.out)
         self.assertIn("Pkg/0.1@lasote/testing: mypackage!!", client.out)
-        self.assertIn("Pkg/0.1@lasote/testing package(): Copied 1 '.h' file: header.h", client.out)
+        self.assertIn("Pkg/0.1@lasote/testing package(): Packaged 1 '.h' file: header.h", client.out)
         # keep build
         client.run("create . Pkg/0.1@lasote/testing --keep-build")
         self.assertIn("Pkg/0.1@lasote/testing: Won't be built as specified by --keep-build",
@@ -111,7 +111,7 @@ def test(self):
         self.assertNotIn("Pkg/0.1@lasote/testing: mysource!!", client.out)
         self.assertNotIn("Pkg/0.1@lasote/testing: mybuild!!", client.out)
         self.assertIn("Pkg/0.1@lasote/testing: mypackage!!", client.out)
-        self.assertIn("Pkg/0.1@lasote/testing package(): Copied 1 '.h' file: header.h", client.out)
+        self.assertIn("Pkg/0.1@lasote/testing package(): Packaged 1 '.h' file: header.h", client.out)
 
         # Changes in the recipe again
         client.save({"conanfile.py": conanfile})
@@ -123,7 +123,7 @@ def test(self):
         self.assertNotIn("Pkg/0.1@lasote/testing: mysource!!", client.out)
         self.assertNotIn("Pkg/0.1@lasote/testing: mybuild!!", client.out)
         self.assertIn("Pkg/0.1@lasote/testing: mypackage!!", client.out)
-        self.assertIn("Pkg/0.1@lasote/testing package(): Copied 1 '.h' file: header.h", client.out)
+        self.assertIn("Pkg/0.1@lasote/testing package(): Packaged 1 '.h' file: header.h", client.out)
 
     def keep_build_error_test(self):
         client = TestClient()
diff --git a/conans/test/functional/command/export_pkg_test.py b/conans/test/functional/command/export_pkg_test.py
--- a/conans/test/functional/command/export_pkg_test.py
+++ b/conans/test/functional/command/export_pkg_test.py
@@ -81,7 +81,7 @@ class HelloPythonConan(ConanFile):
                       client.out)
 
         client.run("export-pkg . Hello/0.1@lasote/stable -pf=pkg")
-        self.assertIn("Hello/0.1@lasote/stable: WARN: No files copied from package folder!",
+        self.assertIn("Hello/0.1@lasote/stable: WARN: No files in this package!",
                       client.out)
 
     def test_package_folder(self):
@@ -100,7 +100,8 @@ def package(self):
 
         client.run("export-pkg . Hello/0.1@lasote/stable -pf=pkg -pr=profile")
         self.assertNotIn("PACKAGE NOT CALLED", client.out)
-        self.assertIn("Hello/0.1@lasote/stable: Copied 1 '.h' file: myfile.h", client.out)
+        self.assertIn("Hello/0.1@lasote/stable: Packaged 1 '.h' file: myfile.h", client.out)
+        self.assertNotIn("No files in this package!", client.out)
         ref = ConanFileReference.loads("Hello/0.1@lasote/stable")
         pkg_folder = client.cache.packages(ref)
         folders = os.listdir(pkg_folder)
@@ -271,10 +272,10 @@ def test_new(self):
         client.run("export-pkg . Hello/0.1@lasote/stable %s" % settings)
         self.assertIn("Hello/0.1@lasote/stable: A new conanfile.py version was exported",
                       client.out)
-        self.assertNotIn("Hello/0.1@lasote/stable package(): WARN: No files copied",
+        self.assertNotIn("Hello/0.1@lasote/stable package(): WARN: No files in this package!",
                          client.out)  # --bare include a now mandatory package() method!
 
-        self.assertIn("Copied 1 '.a' file: libmycoollib.a", client.out)
+        self.assertIn("Packaged 1 '.a' file: libmycoollib.a", client.out)
         self._consume(client, settings + " . -g cmake")
 
         cmakeinfo = load(os.path.join(client.current_folder, "conanbuildinfo.cmake"))
@@ -380,7 +381,7 @@ def package(self):
         # Partial reference is ok
         client.save({CONANFILE: conanfile, "file.txt": "txt contents"})
         client.run("export-pkg . conan/stable")
-        self.assertIn("Hello/0.1@conan/stable package(): Copied 1 '.txt' file: file.txt", client.out)
+        self.assertIn("Hello/0.1@conan/stable package(): Packaged 1 '.txt' file: file.txt", client.out)
 
         # Specify different name or version is not working
         client.run("export-pkg . lib/1.0@conan/stable -f", assert_error=True)
@@ -400,7 +401,7 @@ def package(self):
         # Partial reference is ok
         client.save({CONANFILE: conanfile, "file.txt": "txt contents"})
         client.run("export-pkg . anyname/1.222@conan/stable")
-        self.assertIn("anyname/1.222@conan/stable package(): Copied 1 '.txt' file: file.txt",
+        self.assertIn("anyname/1.222@conan/stable package(): Packaged 1 '.txt' file: file.txt",
                       client.out)
 
     def test_with_deps(self):
diff --git a/conans/test/functional/command/package_test.py b/conans/test/functional/command/package_test.py
--- a/conans/test/functional/command/package_test.py
+++ b/conans/test/functional/command/package_test.py
@@ -47,7 +47,7 @@ def prepare_for_package(the_client):
         # In current dir subdir
         prepare_for_package(client)
         client.run("package . --build-folder build2 --install-folder build --package-folder=subdir")
-        self.assertNotIn("package(): WARN: No files copied", client.out)
+        self.assertNotIn("package(): WARN: No files in this package!", client.out)
         self.assertTrue(os.path.exists(os.path.join(client.current_folder, "subdir")))
 
         # In current dir subdir with conanfile path
@@ -59,7 +59,7 @@ def prepare_for_package(the_client):
         # Default path
         prepare_for_package(client)
         client.run("package . --build-folder build")
-        self.assertNotIn("package(): WARN: No files copied", client.out)
+        self.assertNotIn("package(): WARN: No files in this package!", client.out)
         self.assertTrue(os.path.exists(os.path.join(client.current_folder, "build", "package")))
 
         # Default path with conanfile path
@@ -71,7 +71,7 @@ def prepare_for_package(the_client):
         prepare_for_package(client)
         pf = os.path.join(client.current_folder, "mypackage/two")
         client.run("package . --build-folder build --package-folder='%s'" % pf)
-        self.assertNotIn("package(): WARN: No files copied", client.out)
+        self.assertNotIn("package(): WARN: No files in this package!", client.out)
         self.assertTrue(os.path.exists(os.path.join(client.current_folder, "mypackage", "two")))
 
         # Abs path with conanfile path
@@ -207,8 +207,8 @@ def package(self):
             client.run('package "{0}" --build-folder="{1}/build" '
                        '--package-folder="{2}" --source-folder="{1}/src"'.
                        format(path, conanfile_folder, package_folder))
-        self.assertNotIn("package(): Copied 1 \'\' file", client.out)
-        self.assertIn("package(): Copied 1 file: myapp", client.out)
+        self.assertNotIn("package(): Packaged 1 \'\' file", client.out)
+        self.assertIn("package(): Packaged 1 file: myapp", client.out)
         content = load(os.path.join(package_folder, "include/file.h"))
         self.assertEqual(content, "foo")
         self.assertEqual(sorted(os.listdir(package_folder)),
@@ -234,8 +234,8 @@ def package(self):
                      CONANFILE: conanfile})
         client.run("install . --install-folder=install")
         client.run('package . --source-folder=source --install-folder=install --build-folder=build')
-        self.assertIn("No files copied from source folder!", client.out)
-        self.assertIn("Copied 1 '.lib' file: library.lib", client.out)
+        self.assertNotIn("No files in this package!", client.out)
+        self.assertIn("package(): Packaged 1 '.lib' file: library.lib", client.out)
 
         conanfile = """
 from conans import ConanFile
@@ -248,8 +248,8 @@ def package(self):
 """
         client.save({CONANFILE: conanfile})
         client.run('package . --source-folder=source --install-folder=install --build-folder=build')
-        self.assertIn("No files copied from build folder!", client.out)
-        self.assertIn("Copied 1 '.h' file: file.h", client.out)
+        self.assertNotIn("No files in this package!", client.out)
+        self.assertIn("package(): Packaged 1 '.h' file: file.h", client.out)
 
         conanfile = """
 from conans import ConanFile
@@ -262,7 +262,53 @@ def package(self):
 """
         client.save({CONANFILE: conanfile})
         client.run('package . --source-folder=source --install-folder=install --build-folder=build')
-        self.assertIn("No files copied from source folder!", client.out)
-        self.assertIn("No files copied from build folder!", client.out)
-        self.assertNotIn("Copied 1 '.h' file: file.h", client.out)
-        self.assertNotIn("Copied 1 '.lib' file: library.lib", client.out)
+        self.assertNotIn("No files in this package!", client.out)
+        self.assertIn("package(): Packaged 1 '.h' file: file.h", client.out)
+        self.assertIn("package(): Packaged 1 '.lib' file: library.lib", client.out)
+
+    def installer_package_test(self):
+        """ Simulates installers when packaging the file e.g. cmake install
+            The package() does not use self.copy, but files are copied to package folder
+        """
+        client = TestClient()
+        conanfile = """
+import os
+from conans import ConanFile, tools
+
+class MyConan(ConanFile):
+    def build(self):
+        pass
+    def package(self):
+        tools.save(os.path.join(self.package_folder, "LICENSE.md"), "my license")
+"""
+        client.save({CONANFILE: conanfile})
+        client.run("install .")
+        client.run("package .")
+        self.assertNotIn("No files in this package!", client.out)
+        self.assertIn("package(): Packaged 1 '.md' file: LICENSE.md", client.out)
+        self.assertIn("conanfile.py: Package 'package' created", client.out)
+
+    def empty_package_folder_test(self):
+        """ When the package folder is empty, then an warning should appear
+            and no files must be listed
+        """
+        conanfile = """from conans import ConanFile
+import os
+
+class Pkg(ConanFile):
+    name = "lib"
+    version = "1.0"
+
+    def build(self):
+        pass
+
+    def package(self):
+        self.output.info("yet another conan package")
+"""
+        client = TestClient()
+        client.save({"conanfile.py": conanfile})
+        client.run("install .")
+        client.run("package .")
+        self.assertIn("yet another conan package", client.out)
+        self.assertIn("package(): WARN: No files in this package!", client.out)
+        self.assertNotIn("package(): Packaged", client.out)
diff --git a/conans/test/functional/conanfile/imports_tests.py b/conans/test/functional/conanfile/imports_tests.py
--- a/conans/test/functional/conanfile/imports_tests.py
+++ b/conans/test/functional/conanfile/imports_tests.py
@@ -51,7 +51,7 @@ def package(self):
 """
         client.save({"conanfile.py": conanfile}, clean_first=True)
         client.run("create . Pkg/0.1@user/testing --build=missing")
-        self.assertIn("Pkg/0.1@user/testing package(): Copied 1 '.md' file: LICENSE.md",
+        self.assertIn("Pkg/0.1@user/testing package(): Packaged 1 '.md' file: LICENSE.md",
                       client.out)
         pref = PackageReference(ConanFileReference.loads("Pkg/0.1@user/testing"),
                                 "e6f2dac07251ad9958120a7f7c324366fb3b6f2a")
diff --git a/conans/test/functional/old/conan_trace_file_test.py b/conans/test/functional/old/conan_trace_file_test.py
--- a/conans/test/functional/old/conan_trace_file_test.py
+++ b/conans/test/functional/old/conan_trace_file_test.py
@@ -57,21 +57,21 @@ def _install_a_package(print_commands_to_output, generate_run_log_file):
             return log_file_packaged_, client.user_io.out
 
         log_file_packaged, output = _install_a_package(False, True)
-        self.assertIn("Copied 1 '.log' file: conan_run.log", output)
+        self.assertIn("Packaged 1 '.log' file: conan_run.log", output)
         self.assertTrue(os.path.exists(log_file_packaged))
         contents = load(log_file_packaged)
         self.assertIn("Simulating cmake...", contents)
         self.assertNotIn("----Running------%s> echo" % os.linesep, contents)
 
         log_file_packaged, output = _install_a_package(True, True)
-        self.assertIn("Copied 1 '.log' file: conan_run.log", output)
+        self.assertIn("Packaged 1 '.log' file: conan_run.log", output)
         self.assertTrue(os.path.exists(log_file_packaged))
         contents = load(log_file_packaged)
         self.assertIn("Simulating cmake...", contents)
         self.assertIn("----Running------%s> echo" % os.linesep, contents)
 
         log_file_packaged, output = _install_a_package(False, False)
-        self.assertNotIn("Copied 1 '.log' file: conan_run.log", output)
+        self.assertNotIn("Packaged 1 '.log' file: conan_run.log", output)
         self.assertFalse(os.path.exists(log_file_packaged))
 
     def test_trace_actions(self):
diff --git a/conans/test/integration/complete_test.py b/conans/test/integration/complete_test.py
--- a/conans/test/integration/complete_test.py
+++ b/conans/test/integration/complete_test.py
@@ -23,7 +23,7 @@ def reuse_complete_urls_test(self):
         files = cpp_hello_conan_files("Hello0", "0.1", build=False)
         self.client.save(files)
         self.client.run("create . lasote/stable")
-        self.assertIn("Hello0/0.1@lasote/stable package(): Copied 1 '.h' file: helloHello0.h",
+        self.assertIn("Hello0/0.1@lasote/stable package(): Packaged 1 '.h' file: helloHello0.h",
                       self.client.out)
 
         # Upload package
@@ -53,7 +53,7 @@ def reuse_test(self):
         files = cpp_hello_conan_files("Hello0", "0.1", need_patch=True)
         self.client.save(files)
         self.client.run("create . lasote/stable")
-        self.assertIn("Hello0/0.1@lasote/stable package(): Copied 1 '.h' file: helloHello0.h",
+        self.assertIn("Hello0/0.1@lasote/stable package(): Packaged 1 '.h' file: helloHello0.h",
                       self.client.out)
         # Check compilation ok
         package_ids = self.client.cache.conan_packages(ref)