pkgconfig module: allow custom variables to reference builtin directories

Automatically generate additional variables and write them into the
generated pkg-config file.

This means projects no longer need to manually define the ones they
use, which is annoying for dataonly usages (it used to forbid setting
the base library-relevant "reserved" ones, and now allows it only for
dataonly. But it's bloat to manualy list them anyway).

It also fixes a regression in commit
248e6cf473 which caused libdir to not be
set, and to be unsettable, if the pkg-config file has no libraries but
uses the ${libdir} expansion in a custom variable. This could be
considered likely a case for dataonly, but it's not guaranteed.
pull/9994/head
Eli Schwartz 3 years ago
parent 2d56ff135e
commit 6240920c21
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 31
      docs/markdown/snippets/pkgconfig_directory_variables.md
  2. 57
      mesonbuild/modules/pkgconfig.py
  3. 16
      test cases/common/44 pkgconfig-gen/meson.build
  4. 15
      test cases/common/44 pkgconfig-gen/test.json

@ -0,0 +1,31 @@
## pkgconfig.generate will now include variables for builtin directories when referenced
When using the `variables:` family of kwargs to `pkgconfig.generate` to refer
to installed paths, traditionally only `prefix`, `includedir`, and `libdir`
were available by default, and generating a correct (relocatable) pkg-config
file required manually constructing variables for e.g. `datadir`.
Meson now checks each variable to see if it begins with a reference to a
standard directory, and if so, adds it to the list of directories for which a
builtin variable is created.
For example, before it was necessary to do this:
```meson
pkgconfig.generate(
name: 'bash-completion',
description: 'programmable completion for the bash shell',
dataonly: true,
variables: {
'prefix': get_option('prefix'),
'datadir': join_paths('${prefix}', get_option('datadir')),
'sysconfdir': join_paths('${prefix}', get_option('sysconfdir')),
'compatdir': '${sysconfdir}/bash_completion.d',
'completionsdir': '${datadir}/bash-completion/completions',
'helpersdir': '${datadir}/bash-completion/helpers',
},
install_dir: join_paths(get_option('datadir'), 'pkgconfig'),
)
```
Now the first three variables are not needed.

@ -22,8 +22,9 @@ from .. import build
from .. import dependencies
from .. import mesonlib
from .. import mlog
from ..coredata import BUILTIN_DIR_OPTIONS
from ..dependencies import ThreadDependency
from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs
from ..interpreterbase import permittedKwargs, FeatureNew, FeatureDeprecated, FeatureNewKwargs
if T.TYPE_CHECKING:
from . import ModuleState
@ -329,6 +330,41 @@ class PkgConfigModule(ExtensionModule):
url, version, pcfile, conflicts, variables,
unescaped_variables, uninstalled=False, dataonly=False):
coredata = state.environment.get_coredata()
referenced_vars = set()
optnames = [x.name for x in BUILTIN_DIR_OPTIONS.keys()]
if not dataonly:
# includedir is always implied, although libdir may not be
# needed for header-only libraries
referenced_vars |= {'prefix', 'includedir'}
if deps.pub_libs or deps.priv_libs:
referenced_vars |= {'libdir'}
# also automatically infer variables referenced in other variables
implicit_vars_warning = False
redundant_vars_warning = False
varnames = set()
varstrings = set()
for k, v in variables + unescaped_variables:
varnames |= {k}
varstrings |= {v}
for optname in optnames:
optvar = f'${{{optname}}}'
if any(x.startswith(optvar) for x in varstrings):
if optname in varnames:
redundant_vars_warning = True
else:
# these 3 vars were always "implicit"
if dataonly or optname not in {'prefix', 'includedir', 'libdir'}:
implicit_vars_warning = True
referenced_vars |= {'prefix', optname}
if redundant_vars_warning:
FeatureDeprecated.single_use('pkgconfig.generate variable for builtin directories', '0.62.0',
state.subproject, 'They will be automatically included when referenced',
state.current_node)
if implicit_vars_warning:
FeatureNew.single_use('pkgconfig.generate implicit variable for builtin directories', '0.62.0',
state.subproject, location=state.current_node)
if uninstalled:
outdir = os.path.join(state.environment.build_dir, 'meson-uninstalled')
if not os.path.exists(outdir):
@ -338,18 +374,17 @@ class PkgConfigModule(ExtensionModule):
else:
outdir = state.environment.scratch_dir
prefix = PurePath(coredata.get_option(mesonlib.OptionKey('prefix')))
# These always return paths relative to prefix
libdir = PurePath(coredata.get_option(mesonlib.OptionKey('libdir')))
incdir = PurePath(coredata.get_option(mesonlib.OptionKey('includedir')))
fname = os.path.join(outdir, pcfile)
with open(fname, 'w', encoding='utf-8') as ofile:
if not dataonly:
ofile.write('prefix={}\n'.format(self._escape(prefix)))
if uninstalled:
ofile.write('srcdir={}\n'.format(self._escape(srcdir)))
if deps.pub_libs or deps.priv_libs:
ofile.write('libdir={}\n'.format(self._escape('${prefix}' / libdir)))
ofile.write('includedir={}\n'.format(self._escape('${prefix}' / incdir)))
for optname in optnames:
if optname in referenced_vars - varnames:
if optname == 'prefix':
ofile.write('prefix={}\n'.format(self._escape(prefix)))
else:
dirpath = PurePath(coredata.get_option(mesonlib.OptionKey(optname)))
ofile.write('{}={}\n'.format(optname, self._escape('${prefix}' / dirpath)))
if uninstalled and not dataonly:
ofile.write('srcdir={}\n'.format(self._escape(srcdir)))
if variables or unescaped_variables:
ofile.write('\n')
for k, v in variables:

@ -1,4 +1,4 @@
project('pkgconfig-gen', 'c')
project('pkgconfig-gen', 'c', meson_version: '>=0.60.0')
# Some CI runners does not have zlib, just skip them as we need some common
# external dependency.
@ -149,3 +149,17 @@ ct = custom_target('stat3',
)
simple6 = library('simple6', link_with: ct)
pkgg.generate(simple6)
# implicit variables
pkgg.generate(
name : 'libvartest',
description : 'Check that implicit vars are created',
version : libver,
variables: ['datadir=${prefix}/data', 'foo=${datadir}/foo', 'bar=${bindir}/bar']
)
pkgg.generate(
name : 'libvartest2',
description : 'Check that libdir is not an implicit var',
version : libver,
variables: ['bar=${libdir}/bar']
)

@ -7,11 +7,26 @@
{"type": "file", "file": "usr/lib/pkgconfig/libfoo.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/libhello.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/libhello_nolib.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/libvartest.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/libvartest2.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/simple6.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/ct.pc"},
{"type": "file", "file": "usr/lib/pkgconfig/ct0.pc"}
],
"stdout": [
{
"line": "test cases/common/44 pkgconfig-gen/meson.build:158: WARNING: Project targeting '>=0.60.0' but tried to use feature introduced in '0.62.0': pkgconfig.generate implicit variable for builtin directories."
},
{
"line": "test cases/common/44 pkgconfig-gen/meson.build:164: WARNING: Project targeting '>=0.60.0' but tried to use feature introduced in '0.62.0': pkgconfig.generate implicit variable for builtin directories.",
"count": 0
},
{
"comment": "This will either match in the future-deprecated notice summary, or match the warning summary",
"line": " * 0.62.0: {'pkgconfig.generate variable for builtin directories'}"
}
]
}

Loading…
Cancel
Save