Skip to content

Commit

Permalink
Bugfix/pkconfigdeps (#9341)
Browse files Browse the repository at this point in the history
* Test reproducing the PkgConfigDeps bug

* Added tests reproducing the bug

* Fixed bug. Tests are passing

* Adapted code to Python2.7
  • Loading branch information
franramirez688 committed Jul 29, 2021
1 parent 3f90d6e commit 002eb26
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 12 deletions.
26 changes: 15 additions & 11 deletions conan/tools/gnu/pkgconfigdeps.py
Expand Up @@ -48,33 +48,37 @@ class PkgConfigDeps(object):
def __init__(self, conanfile):
self._conanfile = conanfile

def _get_require_comp_name(self, pkg_name, req):
def _get_require_comp_name(self, dep, req):
# FIXME: this str() is only needed for python2.7 (unicode values). Remove it for Conan 2.0
pkg_name = str(dep.ref.name)
pkg, comp_name = req.split("::") if "::" in req else (pkg_name, req)
req = self._conanfile.dependencies.direct_host[pkg]
# FIXME: it could allow defining requires to not direct dependencies
req = self._conanfile.dependencies.host[pkg]
cmp_name = get_component_alias(req, comp_name)
return cmp_name

def _get_components(self, pkg_name, dep):
def _get_components(self, dep):
ret = []
for comp_name, comp in dep.new_cpp_info.get_sorted_components().items():
comp_genname = get_component_alias(dep, comp_name)
comp_requires_gennames = []
for require in comp.requires:
comp_requires_gennames.append(self._get_require_comp_name(pkg_name, require))
comp_requires_gennames.append(self._get_require_comp_name(dep, require))
ret.append((comp_genname, comp, comp_requires_gennames))
return ret

def _get_public_require_deps(self, comp):
def _get_public_require_deps(self, dep):
public_comp_deps = []
for require in comp.requires:

for require in dep.new_cpp_info.requires:
if "::" in require: # Points to a component of a different package
pkg, cmp_name = require.split("::")
req = self._conanfile.dependencies.direct_host[pkg]
req = dep.dependencies.direct_host[pkg]
public_comp_deps.append(
(get_target_namespace(req), get_component_alias(req, cmp_name)))
else: # Points to a component of same package
public_comp_deps.append((get_target_namespace(self._conanfile),
get_component_alias(self._conanfile, require)))
public_comp_deps.append((get_target_namespace(dep),
get_component_alias(dep, require)))
return public_comp_deps

@property
Expand All @@ -85,7 +89,7 @@ def content(self):
pkg_genname = get_target_namespace(dep)

if dep.new_cpp_info.has_components:
components = self._get_components(dep.ref.name, dep)
components = self._get_components(dep)
for comp_genname, comp_cpp_info, comp_requires_gennames in components:
pkg_comp_genname = "%s-%s" % (pkg_genname, comp_genname)
ret["%s.pc" % pkg_comp_genname] = self._pc_file_content(
Expand All @@ -99,7 +103,7 @@ def content(self):
comp_gennames)
else:
require_public_deps = [_d for _, _d in
self._get_public_require_deps(dep.new_cpp_info)]
self._get_public_require_deps(dep)]
ret["%s.pc" % pkg_genname] = self._pc_file_content(pkg_genname, dep.new_cpp_info,
require_public_deps,
dep.package_folder,
Expand Down
81 changes: 80 additions & 1 deletion conans/test/functional/toolchains/gnu/test_pkgconfigdeps.py
Expand Up @@ -5,6 +5,7 @@

import pytest

from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.tools import TestClient
from conans.util.files import load

Expand Down Expand Up @@ -251,6 +252,84 @@ def package_info(self):
client.save({"conanfile.py": conanfile})
client.run("create . pkg/0.1@")
client.run("install pkg/0.1@ -g PkgConfigDeps")

pc_content = client.load("pkg-mycomponent.pc")
assert "componentdir=${prefix}/mydir" in pc_content


def test_pkg_with_component_requires():
client = TestClient()
client.save({"conanfile.py": GenConanfile("other", "0.1").with_package_file("file.h", "0.1")})
client.run("create . user/channel")

conanfile = textwrap.dedent("""
from conans import ConanFile
class PkgConfigConan(ConanFile):
requires = "other/0.1@user/channel"
def package_info(self):
self.cpp_info.components["mycomponent"].requires.append("other::other")
self.cpp_info.components["myothercomp"].requires.append("mycomponent")
""")
client.save({"conanfile.py": conanfile})
client.run("create . pkg/0.1@")

client2 = TestClient(cache_folder=client.cache_folder)
conanfile = textwrap.dedent("""
[requires]
pkg/0.1
[generators]
PkgConfigDeps
""")
client2.save({"conanfile.txt": conanfile})
client2.run("install .")
pc_content = client2.load("pkg-mycomponent.pc")
assert "Requires: other" in pc_content


def test_pkg_getting_public_requires():
client = TestClient()
conanfile = textwrap.dedent("""
from conans import ConanFile
class Recipe(ConanFile):
def package_info(self):
self.cpp_info.components["cmp1"].libs = ["other_cmp1"]
self.cpp_info.components["cmp2"].libs = ["other_cmp2"]
self.cpp_info.components["cmp3"].requires.append("cmp1")
""")
client.save({"conanfile.py": conanfile})
client.run("create . other/1.0@")

conanfile = textwrap.dedent("""
from conans import ConanFile
class PkgConfigConan(ConanFile):
requires = "other/1.0"
def package_info(self):
self.cpp_info.requires = ["other::cmp1"]
""")
client.save({"conanfile.py": conanfile})
client.run("create . pkg/0.1@")

client2 = TestClient(cache_folder=client.cache_folder)
conanfile = textwrap.dedent("""
[requires]
pkg/0.1
[generators]
PkgConfigDeps
""")
client2.save({"conanfile.txt": conanfile})
client2.run("install .")
pc_content = client2.load("pkg.pc")
assert "Requires: cmp1" in pc_content
assert client2.load("other-cmp1.pc")
assert client2.load("other-cmp2.pc")
pc_content = client2.load("other-cmp3.pc")
assert "Requires: cmp1" in pc_content

0 comments on commit 002eb26

Please sign in to comment.