Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] Add named dependencies #15119

Open
1 task done
lo1ol opened this issue Nov 16, 2023 · 6 comments
Open
1 task done

[feature] Add named dependencies #15119

lo1ol opened this issue Nov 16, 2023 · 6 comments

Comments

@lo1ol
Copy link

lo1ol commented Nov 16, 2023

What is your suggestion?

Hello!

I noticed that there is some requirements by users to be able have several dependencies with the same name but with differences in versions, options or settings:
#660
#4407

I faced with both of this problem: one of my package depends on openssl 3.0 and openssl 1.0 at the same time (in tests). And one of my package depends on some package with different options. There is one workaround for this: include name version or option in name of package. But it still workaround...

I think that this problem can be resolved by adding custom names to dependencies.

self.requires("pkgA/1.0")
self.requires("pkgA/2.0", alias="pkgA_2")
self.requires("pkgA/1.0", options={"option": "value"}, alias="pkgA_modified")

So, generators can search this packages by alias names instead of real names, hash of the requirements should contains alias names conaninfo.txt should contain aliases names instead of original package names.

May be there are some restrictions in implementations of this. But I just want to show you a possible concept.

What do you think about this?

Have you read the CONTRIBUTING guide?

  • I've read the CONTRIBUTING guide
@memsharded
Copy link
Member

Hi @lo1ol

Thanks for your feedback.

There are some reasons why Conan doesn't allow to depend by default on the same package, with different versions or binary variants. For example, if you have one application executable that is linking the zlib library in the zlib/1.2.13 package, it is quite evident that the executable cannot link more than one zlib library. Then requiring both zlib/1.2.13 and zlib/1.3 or trying to require zlib both as a static library and as a shared library doesn't make sense, because you cannot link both into the executable. And then Conan will be raising conflicts or duplicated dependencies if you try to do that.

For other way more exceptional scenarios, it might be possible to depend on more than one version or binary of the same package, that is already doable in Conan 2.0, no need for a new feature: If you define self.requires("pkg/1.2", visible=False, headers=False, libs=False, run=False), you can do that require for different pkg versions and even for different binary variants. There are just some natural limitations:

  • It is not possible to link with those. The generated .cmake files with CMakeDeps will be inexistent or empty, because any attempt to link them will be an error.
  • The information will not be propagated to the consumers of the package that is self.requires() them. Because they will be conflicting again downstream, these visible=False dependencies should remain as a private implementation detail of the package using them
  • visible=False dependencies become isolated and will not conflict with other parts of the dependency graph.

So again, this would be a very exceptional scenario that should be avoided in the vast majority of cases, and for those cases that is desired, Conan 2.0 allows using the requirement traits to address it.

@lo1ol
Copy link
Author

lo1ol commented Nov 17, 2023

Thank you for answer!

It works, but I can't retrieve the package_folder from json output for this kind of dependencies:

{
    "graph": {
        "nodes": {
            "0": {
                "ref": "pkg_a/0.0.1",
...
                },
                "conf_info": {},
                "label": "conanfileA.py (pkg_a/0.0.1)",
                "dependencies": {
                    "1": {
                        "ref": "pkg_b/0.0.1",
                        "run": false,
                        "libs": false,
                        "skip": true,
                        "test": false,
                        "force": false,
                        "direct": true,
                        "build": false,
                        "transitive_headers": null,
                        "transitive_libs": null,
                        "headers": false,
                        "package_id_mode": null,
                        "visible": false
                    }
                },
                "context": "host",
                "test": false
            },
            "1": {
                "ref": "pkg_b/0.0.1#e2a6afab1c5ed8a832feb55cd9c3a3f5",
                "id": "1",
                "recipe": "Cache",
                "package_id": "85c999356992c5713d308db1a4d7bab6bf572f27",
...
                "recipe_folder": "/Users/lo1ol/.conan2/p/pkg_b52f44d89d64fa/e",
                "source_folder": null,
                "build_folder": null,
                "generators_folder": null,
                "package_folder": null,
...
            }
        },
...
    }
}

BTW, if conan 2 support this "workaround", maybe it would be better to add some option, which set this args to False and also add some alias for this deps.

For example:

self.requires("pkg_a/1.0", options={"option": "value"}, local_dep=True, alias="pkg_a_modified")

@memsharded
Copy link
Member

Maybe you are using conan graph info? You should be using conan install, as conan graph info does not really install the package binaries, so package_folder is not defined.

BTW, if conan 2 support this "workaround", maybe it would be better to add some option, which set this args to False and also add some alias for this deps.

You can use the self.dependencies["pkg/version"] with version, to differentiate, or the self.dependencies.get() with the same syntax to obtain the reference to the dependency that you want (or just iterate all self.dependencies)

@lo1ol
Copy link
Author

lo1ol commented Nov 17, 2023

no, I'm using conan install:

# conanfileA.py
from conan import ConanFile

class RtPkcs11EcpConanfile(ConanFile):
    settings = "os", "arch", "build_type"
    name="pkg_a"
    version="0.0.1"

    def build_requirements(self):
        self.requires("pkg_b/0.0.1", visible=False, headers=False, libs=False, run=False)
from conan import ConanFile

class RtPkcs11EcpConanfile(ConanFile):
    settings = "os", "arch", "build_type"
    name="pkg_b"
    version="0.0.1"
conan export-pkg --profile glibc-arm64-gcc11 conanfileB.py
conan install --profile glibc-arm64-gcc11 --format json conanfileA.py
conan --version
Conan version 2.0.14

@lo1ol
Copy link
Author

lo1ol commented Nov 17, 2023

You can use the self.dependencies["pkg/version"] with version, to differentiate, or the self.dependencies.get() with the same syntax to obtain the reference to the dependency that you want (or just iterate all self.dependencies)

Guess, I can. But I just wanted to say that assigning an alias in conanfile makes the search of desired package easer, than searching of desired package by his version or options at generator or somewhere else.

@memsharded
Copy link
Member

Ok, I have checked this.
The above alternative is only feasible at the moment for tool_requires (with build=True), in the "build" context otherwise for regular requires it is not possible.

What you are seeing is that the dependency is being "Skipped", because as it doesn't contain headers, nor libraries, nothing for runtime and not necessary for building, the dependency resolution computes it is not necessary and avoids downloading the binary.

So the above rules apply: it is not possible to require the same dependency in the "host" context multiple times, neither different versions nor different binaries, because it is impossible to link with them.

We will consider in the future a possible "re-packaging" feature (see #13171), that would be the possible scenario that this could make some sense for "host" dependencies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants