conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
8.11k stars 963 forks source link

[bug] build_requires with different #RREV are not used correctly #16312

Open thorsten-klein opened 3 months ago

thorsten-klein commented 3 months ago

Describe the bug

We are using recipe revisions with conan 1.x We have two libraries which depend on same build_requires, but with different #RREV. Conan does not take the correct #RREV of the tool for the library build.

How to reproduce it

Add following test to conans/test/integration/build_requires/build_requires_test.py

def test_build_requires_revisions(self):
        self.server = TestServer()
        client = TestClient(revisions_enabled=True,
                            servers={"default": self.server},
                            users={"default": [("lasote", "mypass")]})

        tool_conanfile = textwrap.dedent("""
        from conans import ConanFile

        class Tool(ConanFile):
            def package_info(self):
                self.output.info("Output1")
                self.env_info.MYVAR.append("Output1")
        """)
        client.save({CONANFILE: tool_conanfile})

        ref = ConanFileReference.loads("Tool/0.1@lasote/stable")

        tool1 = client.export(ref, tool_conanfile)
        client.run("install --build=missing %s" % repr(tool1))
        client.run("upload %s --all" % repr(tool1))

        tool2 = client.export(ref, tool_conanfile.replace("Output1","Output2"))
        client.run("install --build=missing %s" % repr(tool2))
        client.run("upload %s --all" % repr(tool2))

        assert tool1.revision != tool2.revision

        conanfile = textwrap.dedent("""
        from conans import ConanFile

        class MyLib(ConanFile):
            {}

            def build(self):
                self.run("echo MYVAR $MYVAR")
        """)

        lib1 = ConanFileReference.loads("MyLib/0.1@lasote/stable")
        conanfile_lib1 = conanfile.format("""build_requires = '%s'""" % repr(tool1))
        ref_lib_export1 = client.export(lib1, conanfile_lib1)
        client.run("upload %s --all" % repr(lib1))

        lib2 = ConanFileReference.loads("MyOtherLib/0.1@lasote/stable")
        conanfile_lib2 = conanfile.format("""build_requires = '%s'""" % repr(tool2)).replace("MyLib", "MyOtherLib")
        ref_lib_export2 = client.export(lib2, conanfile_lib2)
        client.run("upload %s --all" % repr(lib2))

        conanfile_consumer = textwrap.dedent("""
        from conans import ConanFile

        class MyLib(ConanFile):
            {}

        """)

        ref_consumer = ConanFileReference.loads("Consumer/0.1@lasote/stable")

        conanfile_consumer1 = conanfile_consumer.format("requires = '%s'" % repr(ref_lib_export1))
        ref_consumer_export = client.export(ref_consumer, conanfile_consumer1)
        client.run("install %s --build=* --update" % repr(ref_consumer_export))
        assert "MYVAR Output1" in client.out

        conanfile_consumer2 = conanfile_consumer.format("requires = '%s'" % repr(ref_lib_export2))
        ref_consumer_export = client.export(ref_consumer, conanfile_consumer2)
        client.run("install %s --build=* --update" % repr(ref_consumer_export))
        assert "MYVAR Output2" in client.out

        client.run("remove * -f")
        conanfile_consumer3 = conanfile_consumer.format("""requires = '%s', '%s'""" % (repr(ref_lib_export1), repr(ref_lib_export2)))
        ref_consumer_export = client.export(ref_consumer, conanfile_consumer3)
        client.run("install %s --build=* --update" % repr(ref_consumer_export))
        print(client.out)
        assert "MYVAR Output1" in client.out
        assert "MYVAR Output2" in client.out
thorsten-klein commented 3 months ago

Note: When not using --update then I get expected error

ERROR: The '9fe383f0b6264c07feddde68bf57a649' revision recipe in the local cache doesn't match the requested 'Tool/0.1@lasote/stable#29af85a7594ea33bdcf6c58775e52986'. Use '--update' to check in the remote.

I would expect that --update flag downloads the new correct revision on demand. It seems not to do so.

memsharded commented 3 months ago

Hi @thorsten-klein

Thanks for your report.

This would be a known limitation of the Conan cache in Conan 1.X, it cannot contain more than 1 different revision for the same package-version simultaneously. Consequently the same dependency graph cannot define nor contain 2 different revisions of the same dependency, and if recipes explicitly define requires or tool-requires including a revision, then users need to make sure to align those revisions.

This limitation of the Conan cache in 1.X was one of the important reasons why the major breaking Conan 2 was necessary, the changes in the cache were simply too large to be able to introduce them in Conan 1, it is basically a completely new cache with different paradigm.