pkgconfig: Add support for CustomTarget objects in generator

Fixes: #8618.
pull/8676/head
Xavier Claessens 4 years ago committed by Jussi Pakkanen
parent 8f6ad8e52e
commit 3c64ecaf86
  1. 7
      docs/markdown/Pkgconfig-module.md
  2. 5
      docs/markdown/snippets/pkgconfig_gen_ct.md
  3. 3
      mesonbuild/build.py
  4. 24
      mesonbuild/modules/pkgconfig.py
  5. 7
      run_unittests.py
  6. 19
      test cases/common/45 pkgconfig-gen/meson.build
  7. 4
      test cases/common/45 pkgconfig-gen/test.json

@ -30,11 +30,14 @@ keyword arguments.
also be provided and they will be added into the `Libs` field. Since 0.45.0
dependencies of built libraries will be automatically added, see the
[Implicit dependencies](#implicit-dependencies) section below for the exact
rules.
rules. Since 0.58.0 custom_target() objects are supported as long as they are
linkable (has known extension such as `.a`, `.so`, etc).
- `libraries_private` list of built libraries or strings to put in the
`Libs.private` field. Since 0.45.0 dependencies of built libraries will be
automatically added, see the [Implicit dependencies](#implicit-dependencies)
section below for the exact rules.
section below for the exact rules. Since 0.58.0 custom_target() objects are
supported as long as they are linkable (has known extension such as `.a`,
`.so`, etc).
- `name` the name of this library, used to set the `Name:` field
- `subdirs` which subdirs of `include` should be added to the header
search path, for example if you install headers into

@ -0,0 +1,5 @@
## Passing `custom_target()` output to `pkg.generate()`
It is now allowed to pass libraries generated by a `custom_target()` to
pkg-config file generator. The output filename must have a known library extension
such as `.a`, `.so`, etc.

@ -2601,6 +2601,9 @@ class CustomTargetIndex:
def extract_all_objects_recurse(self):
return self.target.extract_all_objects_recurse()
def get_custom_install_dir(self):
return self.target.get_custom_install_dir()
class ConfigurationData:
def __init__(self) -> None:
super().__init__()

@ -153,6 +153,11 @@ class DependenciesHelper:
obj.link_whole_targets,
obj.external_deps,
isinstance(obj, build.StaticLibrary) and public)
elif isinstance(obj, (build.CustomTarget, build.CustomTargetIndex)):
if not obj.is_linkable_target():
raise mesonlib.MesonException('library argument contains a not linkable custom_target.')
FeatureNew.single_use('custom_target in pkgconfig.generate libraries', '0.58.0', self.state.subproject)
processed_libs.append(obj)
elif isinstance(obj, str):
processed_libs.append(obj)
else:
@ -276,7 +281,13 @@ class DependenciesHelper:
class PkgConfigModule(ExtensionModule):
def _get_lname(self, l, msg, pcfile):
def _get_lname(self, l, msg, pcfile, is_custom_target):
if is_custom_target:
basename = os.path.basename(l.get_filename())
name = os.path.splitext(basename)[0]
if name.startswith('lib'):
name = name[3:]
return name
# Nothing special
if not l.name_prefix_set:
return l.name
@ -373,7 +384,8 @@ class PkgConfigModule(ExtensionModule):
install_dir = l.get_custom_install_dir()[0]
if install_dir is False:
continue
if 'cs' in l.compilers:
is_custom_target = isinstance(l, (build.CustomTarget, build.CustomTargetIndex))
if not is_custom_target and 'cs' in l.compilers:
if isinstance(install_dir, str):
Lflag = '-r${{prefix}}/{}/{}'.format(self._escape(self._make_relative(prefix, install_dir)), l.filename)
else: # install_dir is True
@ -386,18 +398,18 @@ class PkgConfigModule(ExtensionModule):
if Lflag not in Lflags:
Lflags.append(Lflag)
yield Lflag
lname = self._get_lname(l, msg, pcfile)
lname = self._get_lname(l, msg, pcfile, is_custom_target)
# If using a custom suffix, the compiler may not be able to
# find the library
if l.name_suffix_set:
if not is_custom_target and l.name_suffix_set:
mlog.warning(msg.format(l.name, 'name_suffix', lname, pcfile))
if 'cs' not in l.compilers:
if is_custom_target or 'cs' not in l.compilers:
yield '-l%s' % lname
def get_uninstalled_include_dirs(libs):
result = []
for l in libs:
if isinstance(l, str):
if isinstance(l, (str, build.CustomTarget, build.CustomTargetIndex)):
continue
if l.get_subdir() not in result:
result.append(l.get_subdir())

@ -6486,6 +6486,13 @@ class LinuxlikeTests(BasePlatformTests):
self.assertEqual(libhello_nolib.get_pkgconfig_variable('foo', {}), 'bar')
self.assertEqual(libhello_nolib.get_pkgconfig_variable('prefix', {}), self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
if cc.get_id() in {'gcc', 'clang'}:
for name in {'ct', 'ct0'}:
ct_dep = PkgConfigDependency(name, env, kwargs)
self.assertTrue(ct_dep.found())
self.assertIn('-lct', ct_dep.get_link_args())
def test_pkgconfig_gen_deps(self):
'''
Test that generated pkg-config files correctly handle dependencies

@ -101,3 +101,22 @@ stat2 = static_library('stat2', 'simple.c', install: true)
simple4 = library('simple4', 'simple.c', link_with: stat2)
simple5 = library('simple5', 'simple5.c', link_with: simple4, link_whole: stat2)
pkgg.generate(simple5)
# Test passing a linkable CustomTarget and CustomTargetIndex to generator.
# Do this only with gcc/clang to not have to deal with other compiler command
# line specificities.
if cc.get_id() in ['gcc', 'clang']
ct = custom_target('ct',
input: 'simple.c',
output: 'libct.so',
command: [cc.cmd_array(), '@INPUT@', '-shared', '-o', '@OUTPUT@'],
)
pkgg.generate(libraries: ct,
name: 'ct',
description: 'custom target'
)
pkgg.generate(libraries: ct[0],
name: 'ct0',
description: 'custom target index'
)
endif

@ -8,6 +8,8 @@
{"type": "file", "file": "usr/lib/pkgconfig/libhello_nolib.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/simple2.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/simple3.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/simple5.pc"}
{"type": "file", "file": "usr/lib/pkgconfig/simple5.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/ct.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/ct0.pc"}
]
}

Loading…
Cancel
Save