conan-io / conan

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

[question] Manually injecting Requires.private into pkg-config modules #16587

Closed fpoirotte closed 1 day ago

fpoirotte commented 2 days ago

What is your question?

Hi!

I'm using Conan 2.4.1 and writing custom Conan recipes for packages which are usually consumed using pkg-config. In the upstream files on one such project, the installed.pc files adds versioned constraints inside a Requires.private line, specifically:

Requires.private: xau >= 0.99.2

In my recipe, I extracted the line in the package() method (it gets written to a YAML file), then in the package_info() method, I add the line containing the dependency to the component, using the following code:

    def package_info(self):
        xcb_proto_version = self.dependencies["xcb-proto"].ref.version

        for filename, data in yaml.safe_load(open(self._pc_data_path)).items():
            self.cpp_info.components[filename].libs.extend([filename])
            self.cpp_info.components[filename].version = self.version
            self.cpp_info.components[filename].set_property("pkg_config_name", filename)

            # This is the code responsible for copying the private requirements
            if "private_requires" in data:
                custom = "Requires.private: {}".format(data['private_requires'])
            else:
                custom = ""

            if filename == "xcb":
                custom += "\nxcbproto_version={}".format(xcb_proto_version)

            if custom:
                self.cpp_info.components[filename].set_property("pkg_config_custom_content", custom)

        self.cpp_info.components["xcb"].requires.extend(["libxau::libxau", "xcb-proto::xcb-proto", "libpthread-stubs::libpthread-stubs"])

However, when the consumer tries to check the dependency's availability, pkgconf raises the following error:

Package dependency requirement 'libxau >= .99.2' could not be satisfied.
Package 'libxau' has version '1.0.11', required version is '>= .99.2'

Inspecting the generated .pc file manually reveals that the space after the ">=" operator has been removed. Manually adding the space character back indeed fixes the error.

On the Conan side, this is caused by the _get_pc_variables() in tools/gnu/pkgconfigdeps.py. The code seems to assume that every line in pkg_config_custom_content is used to define variables.

My question is thus: is this expected behavior? Is pkg_config_custom_content supposed to only declare variables? If so, how do you usually deal with this kind of versioned requirements in pkg-config .pc files?

Note: I've opened an issue in pkgconf as well (https://github.com/pkgconf/pkgconf/issues/359) to clarify the behavior (and hopefully, make the parser a bit more lenient).

Have you read the CONTRIBUTING guide?

memsharded commented 2 days ago

Hi @fpoirotte

Thanks for your question.

The code seems to assume that every line in pkg_config_custom_content is used to define variables.

My question is thus: is this expected behavior? Is pkg_config_custom_content supposed to only declare variables?

Yes, the pkg_config_custom_content is intended to be a dict (still legacy string that will be parsed to form a dict is supported, but considered legacy), it seems this has been the need so far and this property was defined to satisfy this use case.

If so, how do you usually deal with this kind of versioned requirements in pkg-config .pc files?

The thing is that in general it is not necessary to do these changes. Conan already handles it, like the versions in the dependencies will be the versions defined by Conan recipe requires, not others. The .pc files don't need to check or define anything. Likewise the visibility or "private" definition in .pc is not very necessary, as it will be mostly managed by Conan requirement traits.

fpoirotte commented 1 day ago

Thank you for the quick answer. I'll remove the explicit Requires line and update the recipe to use a dict instead of a string.