conan-io / conan

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

[question] How to access dependency option values in a Generator in conan2 #17017

Closed daseix closed 3 weeks ago

daseix commented 3 weeks ago

What is your question?

We are in the transition from conan1 to conan2. Currently we have a custom generator that generates a file containing all options for dependencies. For conan1 we accessed this using (according to #4189)

class deps_options:
    def __init__(self, conanfile: ConanFile):
        self._conanfile = conanfile

    @property
    def output_path(self) -> str:
        return os.path.join(self._conanfile.generators_folder, self.filename)

    @property
    def filename(self) -> str:
        return "rk_deps_options.inc.yaml"

    @property
    def content(self) -> str:
        options = []
        for mod, values in self.conanfile.options.deps_package_values.items():
            if mod != "robotkernel_installer":
                for key, val in values.items():
                    options.append(f"- {mod}/*:{key}={val}\n")
        options.sort()
        return "".join(options)

    def generate(self) -> None:
        save(self._conanfile, self.output_path, self.content)

However, self.conanfile.options.deps_package_values seems to be no longer available in conan2. I found self._conanfile.options._deps_package_options, but this for some reason is always empty.

How can I access the dependency options in conan2?

Conan version 2.7.0 Python 3.9.13

Have you read the CONTRIBUTING guide?

AbrilRBS commented 3 weeks ago

Hi @daseix thanks a lot for your question.

As shown in https://docs.conan.io/2/reference/conanfile/methods/generate.html#conan-conanfile-model-dependencies Conan 2 (And Conan 1 too, as this was backported to Conan 1), now uses the self.dependencies attribute to access dependency information.

Your usage would thus be something like:

options = []
for require, dependency in self.dependencies.items():
    ir dependency.ref.name != "robotkernel_installer":
        for option in dependency.options.possible_values:
            options.append(f"- {dependency.ref}:{option}={dependency.options.get_safe(option)}")
options.sort()
return "".join(options)

Note that the dependency.ref accessor will set the name/version in the option line, if you want to have name/* as before, you should change that line with options.append(f"- {dependency.ref.name}/*:{option}={dependency.options.get_safe(option)}")

Let me know is this helps, happy to help if you have any more questions, thanks!

daseix commented 3 weeks ago

thank you very much, this helped solving my problem!