Skip to content

Commit

Permalink
Alternative way of setting properties that depend on generator specif…
Browse files Browse the repository at this point in the history
…ic features. (#8727)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* fix

* wip

* wip

* wip

* wip

* remove unused

* wip

* wip

* wip

* wip

* wip

* minor changes

* wip

* fix local flow

* wip

* simplify code

* change update function name

* generalize name

* start build modules support

* wip

* wip

* update test

* old behaviour

* wip

* wip

* add custom content to pkg-config generator

* add tests with components

* add some unit tests

* remove translate

* revert changes

* revert changes

* revert changes

* use other properties names

* update tests

* fix filename

* fix gets

* add tests

* fix test

* add note

* test multi

* move to integration

* fix name

* revert change

* add more tests

* remove argument

* review

* review

* minor refactor

* change name

* fix stylistic things

* cache ret val

* correct caching

Co-authored-by: memsharded <james@conan.io>
  • Loading branch information
czoido and memsharded authored Apr 15, 2021
1 parent 9f2608e commit e54e371
Show file tree
Hide file tree
Showing 5 changed files with 393 additions and 6 deletions.
4 changes: 4 additions & 0 deletions conans/client/generators/pkg_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ def _pc_file_content(self, name, cpp_info, requires_gennames):
includedir_vars = varnames
lines.extend(dir_lines)

pkg_config_custom_content = cpp_info.get_property("pkg_config_custom_content", self.name)
if pkg_config_custom_content:
lines.append(pkg_config_custom_content)

lines.append("")
lines.append("Name: %s" % name)
description = cpp_info.description or "Conan package: %s" % name
Expand Down
58 changes: 52 additions & 6 deletions conans/model/build_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class _CppInfo(object):

def __init__(self):
self._name = None
self._generator_properties = {}
self.names = {}
self.system_libs = [] # Ordered list of system libraries
self.includedirs = [] # Ordered list of include paths
Expand All @@ -127,6 +128,7 @@ def __init__(self):
self.sysroot = ""
self.requires = []
self._build_modules_paths = None
self._build_modules = None
self._include_paths = None
self._lib_paths = None
self._bin_paths = None
Expand Down Expand Up @@ -154,7 +156,9 @@ def build_modules_paths(self):
conan_v2_error("Use 'self.cpp_info.build_modules[\"<generator>\"] = "
"{the_list}' instead".format(the_list=self.build_modules))
self.build_modules = BuildModulesDict.from_list(self.build_modules)
tmp = dict_to_abs_paths(BuildModulesDict(self.build_modules), self.rootpath)
# Invalidate necessary, get_build_modules used raise_incorrect_components_definition
self._build_modules = None
tmp = dict_to_abs_paths(BuildModulesDict(self.get_build_modules()), self.rootpath)
self._build_modules_paths = tmp
return self._build_modules_paths

Expand Down Expand Up @@ -209,15 +213,58 @@ def name(self):
def name(self, value):
self._name = value

# TODO: Deprecate for 2.0. Only cmake and pkg_config generators should access this.
# Use get_property for 2.0
def get_name(self, generator):
return self.names.get(generator, self._name)

property_name = None
if "cmake" in generator:
property_name = "cmake_target_name"
elif "pkg_config" in generator:
property_name = "pkg_config_name"
return self.get_property(property_name, generator) or self.names.get(generator, self._name)

# TODO: Deprecate for 2.0. Only cmake generators should access this. Use get_property for 2.0
def get_filename(self, generator):
result = self.filenames.get(generator)
result = self.get_property("cmake_file_name", generator) or self.filenames.get(generator)
if result:
return result
return self.get_name(generator)

# TODO: Deprecate for 2.0. Use get_property for 2.0
def get_build_modules(self):
if self._build_modules is None: # Not cached yet
try:
default_build_modules_value = self._generator_properties[None]["cmake_build_modules"]
except KeyError:
ret_dict = {}
else:
ret_dict = {"cmake_find_package": default_build_modules_value,
"cmake_find_package_multi": default_build_modules_value,
"cmake": default_build_modules_value,
"cmake_multi": default_build_modules_value}

for generator, values in self._generator_properties.items():
if generator:
v = values.get("cmake_build_modules")
if v:
ret_dict[generator] = v
self._build_modules = ret_dict if ret_dict else self.build_modules
return self._build_modules

def set_property(self, property_name, value, generator=None):
self._generator_properties.setdefault(generator, {})[property_name] = value

def get_property(self, property_name, generator=None):
if generator:
try:
return self._generator_properties[generator][property_name]
except KeyError:
pass
try:
return self._generator_properties[None][property_name]
except KeyError:
pass

# Compatibility for 'cppflags' (old style property to allow decoration)
def get_cppflags(self):
conan_v2_error("'cpp_info.cppflags' is deprecated, use 'cxxflags' instead")
Expand Down Expand Up @@ -354,7 +401,7 @@ def _raise_incorrect_components_definition(self, package_name, package_requires)
self.cxxflags or
self.sharedlinkflags or
self.exelinkflags or
self.build_modules or
self.get_build_modules() or
self.requires):
raise ConanException("self.cpp_info.components cannot be used with self.cpp_info "
"global values at the same time")
Expand Down Expand Up @@ -437,7 +484,6 @@ def merge_lists(seq1, seq2):
self.cflags = merge_lists(dep_cpp_info.cflags, self.cflags)
self.sharedlinkflags = merge_lists(dep_cpp_info.sharedlinkflags, self.sharedlinkflags)
self.exelinkflags = merge_lists(dep_cpp_info.exelinkflags, self.exelinkflags)

if not self.sysroot:
self.sysroot = dep_cpp_info.sysroot

Expand Down
55 changes: 55 additions & 0 deletions conans/test/functional/generators/pkg_config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,58 @@ def test_empty_include(self):
pc = client.load("pkg.pc")
self.assertNotIn("libdir=${prefix}/lib", pc)
self.assertNotIn("includedir=${prefix}/include", pc)

def test_custom_content(self):
# https://github.com/conan-io/conan/issues/7661
conanfile = textwrap.dedent("""
from conans import ConanFile
from conans.tools import save
import os
import textwrap
class PkgConfigConan(ConanFile):
def package(self):
save(os.path.join(self.package_folder, "include" ,"file"), "")
save(os.path.join(self.package_folder, "lib" ,"file"), "")
def package_info(self):
custom_content = textwrap.dedent(\"""
datadir=${prefix}/share
schemasdir=${datadir}/mylib/schemas
bindir=${prefix}/bin
\""")
self.cpp_info.set_property("pkg_config_custom_content", custom_content)
self.cpp_info.includedirs = ["include"]
self.cpp_info.libdirs = ["lib"]
""")
client = TestClient()
client.save({"conanfile.py": conanfile})
client.run("create . pkg/0.1@")
client.run("install pkg/0.1@ -g pkg_config")

pc_content = client.load("pkg.pc")
self.assertIn("libdir=${prefix}/lib", pc_content)
self.assertIn("datadir=${prefix}/share", pc_content)
self.assertIn("schemasdir=${datadir}/mylib/schemas", pc_content)
self.assertIn("bindir=${prefix}/bin", pc_content)
self.assertIn("Name: pkg", pc_content)

def test_custom_content_components(self):
conanfile = textwrap.dedent("""
from conans import ConanFile
from conans.tools import save
import os
import textwrap
class PkgConfigConan(ConanFile):
def package_info(self):
self.cpp_info.components["mycomponent"].set_property("pkg_config_custom_content",
"componentdir=${prefix}/mydir")
""")
client = TestClient()
client.save({"conanfile.py": conanfile})
client.run("create . pkg/0.1@")
client.run("install pkg/0.1@ -g pkg_config")

pc_content = client.load("mycomponent.pc")
self.assertIn("componentdir=${prefix}/mydir", pc_content)
Loading

0 comments on commit e54e371

Please sign in to comment.