Repository: conan-io/conan

Issue:
[feature] missing prebuilt package should have capability to provide more details
This is somewhat a duplicate of: 
#3316 which was closed by #3438 
Its better now, but maybe it oculd be slightly better?

Its still guessing game for me:

# Back story:
Right now due to a various choices we have made we do not encourage our users to use --build missing whenever they see it. instead we have prebuilt binaries in our artifactory.

We are often met with an error like:
Missing prebuilt library X. 

Conans error is very cryptic here, it basically does not provide any diagnostic why the available binaries you have are not compatible with your package, its always guessing game.

It would be nice if there was an option to ask conan for verbose output where it would state:

You have available prebuilt bianry with following configs:  
" now prints a matrix of all prebuilt binaries for that particular version"

Whereas you require this package to have a particular set of options:
" now prints a set of option that conan searched for."


# Right now what it prints is soemthing like this:
```
bzip2/1.0.8: WARN: Can't find a 'bzip2/1.0.8' package for the specified settings, options and dependencies:
- Settings: arch=x86_64, build_type=Debug, compiler=gcc, compiler.version=8, os=Linux, os.version=rh6
- Options: build_executable=True, fPIC=True, shared=False
- Dependencies: 
- Package ID: f610127d9b93ffcf379adc4fddaeeacc2308a891

ERROR: Missing prebuilt package for 'bzip2/1.0.8'
Try to build it from sources with "--build bzip2"
Or read "http://docs.conan.io/en/latest/faq/troubleshooting.html#error-missing-prebuilt-package"
```

Okay it prints the Options conan is looking for - but it does not highlight what are the available packages. 
My way of solving this is to go to artifactory, and click through prebuilt binaries  and compare each option by hand which particular option has not been found. 
Couldnt it just dump that information straight out? 
And actually I dont think its possible to list prebuilt binary options via conan CLI?


- [X ] I've read the [CONTRIBUTING guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).



Discussion:
It is possible to do a couple of things:

- You can do a ``conan search <pkg-ref> --table=file.html``, and it will create a table with settings and options for the available binaries.
- You can also do a ``conan search <pkg-ref> -q "os=Windows AND compiler=gcc"``, and query/filter the search results.

The first is not added automatically to the output because it is too much to generate an html file and open a browser, will be more confusing to the user.
Thats lovely.
Its probabyl exactly what I was looking for. 

Closing.
Hello @memsharded 
I am opening this issue, I think conan should definitely have more verbose syntax.
this is the error I get:
```
Library/1.2@user/channel: WARN: Can't find a 'Library/1.2@library/stable' package for the specified settings, options and dependencies:
- Settings: arch=x86_64, build_type=Release, compiler=gcc, compiler.libcxx=libstdc++11, compiler.version=8, cppstd=17, os=Linux, os.version=rh7
- Options: shared=True
- Dependencies: AnotherLibrary/0.7@user/channel
- Package ID: d435ee8036bb0df9cf015e57c4d79566293f3644

ERROR: Missing prebuilt package for 'Library/1.2@user/channel'
```

Problem here turned out to be that i changed the default_package_id_mode. and Library was not build with this patch_mode version.

However the issue is much greater than that, 
You pointed me towards `conan search`.
In cases where the problem is with binary compatibility across the tree - `conan search` advice is not a very good one - as problem is with versioning_schema mismatch rather than some options mismatch.

This is basically what I am doing every other day ( as we publish binaries into artifactory. ) Every other day I see missing prebuilt and conan is not good at all at telling me exactly why packages were not mismatch.

Mind you I am now very very good at guessing the mismatch rootcause - however if anyone else would see these issues it would take them hours of frustration to understand what the hell is going on.


I think conan should try to analyze available prebuild binaries and hint why its not wroking.
In worst case it should hint what commands will guide the user to find the rootcause. 
linking to troubleshooting is just not good enough, Especially as it just tells the user to just 'build' missing tree, rather than instructing on how to find it.


Consider below example:
```
$ cat liba/conanfile:
from conans import ConanFile, tools

class Conan(ConanFile):
    name = "liba"
    pass

$cat libb/conanfile.py 
from conans import ConanFile, tools

class Conan(ConanFile):
    name = "libb"
    requires="liba/1.0"
    pass

$ cat libc/conanfile.py 
from conans import ConanFile, tools

class Conan(ConanFile):
    name="libc"
    requires="libb/1.0", "liba/1.1"
```

using global_package_id_mode patch_mode will error with:
```
libb/1.0: WARN: Can't find a 'libb/1.0' package for the specified settings, options and dependencies:
- Settings: 
- Options: 
- Dependencies: liba/1.1
- Package ID: 96f50b175e9b178f3e456b660ca2f11dbea3b6ef

ERROR: Missing prebuilt package for 'libb/1.0'
Try to build it from sources with "--build libb"
Or read "http://docs.conan.io/en/latest/faq/troubleshooting.html#error-missing-prebuilt-package"
```

Of course this is a trivial example, only dependencies has any entries. 
I think it would be possible for conan to iterate over prebuilt packages (even if hidden behind a flag) and print exactly why each prebuilt package is not compatible.
@uilianries 

I would try to add in:
```python
    def _raise_missing(self, missing):
        ...
        dependencies = [str(dep.dst) for dep in node.dependencies]
        raise_package_not_found_error(conanfile, ref, package_id, dependencies,
                                      out=conanfile.output, recorder=self._recorder)
```

- Do not modify the current information
- Add a new displayed field, that lists the information from the ``ConanInfo.requires``, which is the one used to compute the hash.

I think that might alleviate a bit this pain. 
Hm, not sure how exactly would that work but.
We were thinking that if you are worried about introducing a overhead on this, maybe adding a flag --debug-missing or sth and then conan would actually scan the prebuilt packages that exist and compare everything one by one providing some sort of table? 

I  was thinking of looking into that and contributing but would definitlely need some help. 
similarly how `conan search` works but rather: 1st column would be: what your current setup requires and all other columns would be what you need.
> I was thinking of looking into that and contributing but would definitlely need some help.
similarly how conan search works but rather: 1st column would be: what your current setup requires and all other columns would be what you need.

Well, the problem is that ``conan search`` does not (and can not) handle dependencies information, for that you need the full graph evaluation, which is unfeasible. If it is only a ``settings`` and ``options`` configuration, then yes, ``conan search`` (I guess you mean the ``--table`` argument) might be improved to show more information. Probably some combination of the ``--query`` argument, that could be used to highlight cells in the html table?

What I was thinking above is to display not only the direct dependencies (``requires``) information, but showing all the dependencies, including transitive, in the form that they define the package ID, i.e, something like (``pkgA/1.X.Y``, ``pkgB/1.2.3@user/channel#revision``, etc). I think that could help a bit to identify possible missing reasons regarding dependencies and ``package_id_mode``.

Resolving patch:
diff --git a/conans/client/installer.py b/conans/client/installer.py
--- a/conans/client/installer.py
+++ b/conans/client/installer.py
@@ -268,13 +268,15 @@ def raise_package_not_found_error(conan_file, ref, package_id, dependencies, out
     settings_text = ", ".join(conan_file.info.full_settings.dumps().splitlines())
     options_text = ", ".join(conan_file.info.full_options.dumps().splitlines())
     dependencies_text = ', '.join(dependencies)
+    requires_text = ", ".join(conan_file.info.requires.dumps().splitlines())
 
     msg = '''Can't find a '%s' package for the specified settings, options and dependencies:
 - Settings: %s
 - Options: %s
 - Dependencies: %s
+- Requirements: %s
 - Package ID: %s
-''' % (ref, settings_text, options_text, dependencies_text, package_id)
+''' % (ref, settings_text, options_text, dependencies_text, requires_text, package_id)
     out.warn(msg)
     recorder.package_install_error(PackageReference(ref, package_id), INSTALL_ERROR_MISSING, msg)
     raise ConanException('''Missing prebuilt package for '%s'


Test patch:
diff --git a/conans/test/functional/package_id/package_id_requires_modes_test.py b/conans/test/functional/package_id/package_id_requires_modes_test.py
--- a/conans/test/functional/package_id/package_id_requires_modes_test.py
+++ b/conans/test/functional/package_id/package_id_requires_modes_test.py
@@ -455,3 +455,37 @@ def test_std_matching_with_compiler_cppstd(self):
                         ' -s compiler="gcc" -s compiler.libcxx=libstdc++11'
                         ' -s compiler.version=7.2 -s compiler.cppstd=gnu14')
         self.assertIn("Hello/1.2.0@user/testing: Already installed!", self.client.out)
+
+    def test_package_id_requires_patch_mode(self):
+        """ Requirements shown in build missing error, must contains transitive packages
+            For this test the follow graph has been used:
+            libb <- liba
+            libfoo <- libbar
+            libc <- libb, libfoo
+            libd <- libc
+        """
+
+        channel = "user/testing"
+        self.client.run("config set general.default_package_id_mode=patch_mode")
+        self._export("liba", "0.1.0", channel=channel, package_id_text=None, requires=None)
+        self.client.run("create . liba/0.1.0@user/testing")
+        self._export("libb", "0.1.0", channel=channel, package_id_text=None, requires=["liba/0.1.0@user/testing"])
+        self.client.run("create . libb/0.1.0@user/testing")
+        self._export("libbar", "0.1.0", channel=channel, package_id_text=None, requires=None)
+        self.client.run("create . libbar/0.1.0@user/testing")
+        self._export("libfoo", "0.1.0", channel=channel, package_id_text=None, requires=["libbar/0.1.0@user/testing"])
+        self.client.run("create . libfoo/0.1.0@user/testing")
+        self._export("libc", "0.1.0", channel=channel, package_id_text=None,
+                     requires=["libb/0.1.0@user/testing", "libfoo/0.1.0@user/testing"])
+        self._export("libd", "0.1.0", channel=channel, package_id_text=None, requires=["libc/0.1.0@user/testing"])
+        self.client.run("create . libd/0.1.0@user/testing", assert_error=True)
+        self.assertIn("""ERROR: Missing binary: libc/0.1.0@user/testing:e12c9d31fa508340bb8d0c4f9dd4c98a5d0ac082
+
+libc/0.1.0@user/testing: WARN: Can't find a 'libc/0.1.0@user/testing' package for the specified settings, options and dependencies:
+- Settings: 
+- Options: an_option=off, liba:an_option=off, libb:an_option=off, libbar:an_option=off, libfoo:an_option=off
+- Dependencies: libb/0.1.0@user/testing, libfoo/0.1.0@user/testing
+- Requirements: liba/0.1.0, libb/0.1.0, libbar/0.1.0, libfoo/0.1.0
+- Package ID: e12c9d31fa508340bb8d0c4f9dd4c98a5d0ac082
+
+ERROR: Missing prebuilt package for 'libc/0.1.0@user/testing'""", self.client.out)