pkgconfig: add suppport for custom variables during generation

Usage:
    pkgconfig.generate(
      ...
      description : 'A library with custom variables.',
      variables : ['foo=bar', 'datadir=${prefix}/data']
      )

The variables 'prefix', 'libdir' and 'includedir' are reserved, meson will
fail with an error message.

Variables can reference each other with the pkgconfig notation, e.g.

   variables : ['datadir=${prefix}/data',
                'otherdatadir=${datadir}/other']

meson does not check this for correctness or that the referenced variable
exists, we merely keep the same order as specified.
pull/1777/head
Peter Hutterer 8 years ago committed by Jussi Pakkanen
parent 1aa68cf6e3
commit 7ed19902be
  1. 1
      docs/markdown/Pkgconfig-module.md
  2. 14
      docs/markdown/Release-notes-for-0.41.0.md
  3. 33
      mesonbuild/modules/pkgconfig.py
  4. 2
      run_unittests.py
  5. 4
      test cases/common/51 pkgconfig-gen/meson.build
  6. 16
      test cases/failing/47 pkgconfig variables reserved/meson.build
  7. 5
      test cases/failing/47 pkgconfig variables reserved/simple.c
  8. 6
      test cases/failing/47 pkgconfig variables reserved/simple.h
  9. 16
      test cases/failing/48 pkgconfig variables zero length/meson.build
  10. 5
      test cases/failing/48 pkgconfig variables zero length/simple.c
  11. 6
      test cases/failing/48 pkgconfig variables zero length/simple.h
  12. 16
      test cases/failing/49 pkgconfig variables zero length value/meson.build
  13. 5
      test cases/failing/49 pkgconfig variables zero length value/simple.c
  14. 6
      test cases/failing/49 pkgconfig variables zero length value/simple.h
  15. 16
      test cases/failing/50 pkgconfig variables not key value/meson.build
  16. 5
      test cases/failing/50 pkgconfig variables not key value/simple.c
  17. 6
      test cases/failing/50 pkgconfig variables not key value/simple.h

@ -20,3 +20,4 @@ The generated file's properties are specified with the following keyword argumen
- `requires_private` list of strings to put in the `Requires.private` field
- `libraries_private` list of strings to put in the `Libraries.private` field
- `install_dir` the directory to install to, defaults to the value of option `libdir` followed by `/pkgconfig`
- `variables` a list of strings with custom variables to add to the generated file. The strings must be in the form `name=value` and may reference other pkgconfig variables, e.g. `datadir=${prefix}/share`. The names `prefix`, `libdir` and `installdir` are reserved and may not be used.

@ -24,3 +24,17 @@ The ninja backend now quotes special characters that may be interpreted by
ninja itself, providing better interoperability with custom commands. This
support may not be perfect; please report any issues found with special
characters to the issue tracker.
## Pkgconfig support for custom variables
The Pkgconfig module object can add arbitrary variables to the generated .pc
file with the new `variables` keyword:
```meson
pkg.generate(libraries : libs,
subdirs : h,
version : '1.0',
name : 'libsimple',
filebase : 'simple',
description : 'A simple demo library.',
variables : ['datadir=${prefix}/data'])
```

@ -43,7 +43,7 @@ class PkgConfigModule(ExtensionModule):
def generate_pkgconfig_file(self, state, libraries, subdirs, name, description,
url, version, pcfile, pub_reqs, priv_reqs,
conflicts, priv_libs):
conflicts, priv_libs, variables):
coredata = state.environment.get_coredata()
outdir = state.environment.scratch_dir
fname = os.path.join(outdir, pcfile)
@ -53,6 +53,8 @@ class PkgConfigModule(ExtensionModule):
# 'os.path.join' for details)
ofile.write('libdir=%s\n' % os.path.join('${prefix}', coredata.get_builtin_option('libdir')))
ofile.write('includedir=%s\n' % os.path.join('${prefix}', coredata.get_builtin_option('includedir')))
for k, v in variables:
ofile.write('%s=%s\n' % (k, v))
ofile.write('\n')
ofile.write('Name: %s\n' % name)
if len(description) > 0:
@ -136,6 +138,33 @@ class PkgConfigModule(ExtensionModule):
pub_reqs = mesonlib.stringlistify(kwargs.get('requires', []))
priv_reqs = mesonlib.stringlistify(kwargs.get('requires_private', []))
conflicts = mesonlib.stringlistify(kwargs.get('conflicts', []))
def parse_variable_list(stringlist):
reserved = ['prefix', 'libdir', 'includedir']
variables = []
for var in stringlist:
# foo=bar=baz is ('foo', 'bar=baz')
l = var.split('=', 1)
if len(l) < 2:
raise mesonlib.MesonException('Variables must be in \'name=value\' format')
name, value = l[0].strip(), l[1].strip()
if not name or not value:
raise mesonlib.MesonException('Variables must be in \'name=value\' format')
# Variable names must not contain whitespaces
if any(c.isspace() for c in name):
raise mesonlib.MesonException('Invalid whitespace in assignment "{}"'.format(var))
if name in reserved:
raise mesonlib.MesonException('Variable "{}" is reserved'.format(name))
variables.append((name, value))
return variables
variables = parse_variable_list(mesonlib.stringlistify(kwargs.get('variables', [])))
pcfile = filebase + '.pc'
pkgroot = kwargs.get('install_dir', None)
if pkgroot is None:
@ -144,7 +173,7 @@ class PkgConfigModule(ExtensionModule):
raise mesonlib.MesonException('Install_dir must be a string.')
self.generate_pkgconfig_file(state, libs, subdirs, name, description, url,
version, pcfile, pub_reqs, priv_reqs,
conflicts, priv_libs)
conflicts, priv_libs, variables)
res = build.Data(mesonlib.File(True, state.environment.get_scratch_dir(), pcfile), pkgroot)
return ModuleReturnValue(res, [res])

@ -1174,6 +1174,8 @@ class LinuxlikeTests(BasePlatformTests):
self.assertTrue(simple_dep.found())
self.assertEqual(simple_dep.get_version(), '1.0')
self.assertIn('-lfoo', simple_dep.get_link_args())
self.assertEqual(simple_dep.get_pkgconfig_variable('foo'), 'bar')
self.assertPathEqual(simple_dep.get_pkgconfig_variable('datadir'), '/usr/data')
def test_vala_c_warnings(self):
'''

@ -41,4 +41,6 @@ pkgg.generate(
libraries : lib2,
name : 'libfoo',
version : libver,
description : 'A foo library.')
description : 'A foo library.',
variables : ['foo=bar', 'datadir=${prefix}/data']
)

@ -0,0 +1,16 @@
project('variables-reserved-test', 'c', version : '1.0')
pkgg = import('pkgconfig')
lib = shared_library('simple', 'simple.c')
libver = '1.0'
h = install_headers('simple.h')
pkgg.generate(
libraries : [lib, '-lz'],
subdirs : '.',
version : libver,
name : 'libsimple',
filebase : 'simple',
description : 'A simple demo library.',
variables : [ 'prefix=/tmp/' ]
)

@ -0,0 +1,5 @@
#include"simple.h"
int simple_function() {
return 42;
}

@ -0,0 +1,6 @@
#ifndef SIMPLE_H_
#define SIMPLE_H_
int simple_function();
#endif

@ -0,0 +1,16 @@
project('variables-zero-length-test', 'c', version : '1.0')
pkgg = import('pkgconfig')
lib = shared_library('simple', 'simple.c')
libver = '1.0'
h = install_headers('simple.h')
pkgg.generate(
libraries : [lib, '-lz'],
subdirs : '.',
version : libver,
name : 'libsimple',
filebase : 'simple',
description : 'A simple demo library.',
variables : [ '=value' ]
)

@ -0,0 +1,5 @@
#include"simple.h"
int simple_function() {
return 42;
}

@ -0,0 +1,6 @@
#ifndef SIMPLE_H_
#define SIMPLE_H_
int simple_function();
#endif

@ -0,0 +1,16 @@
project('variables-zero-length-value-test', 'c', version : '1.0')
pkgg = import('pkgconfig')
lib = shared_library('simple', 'simple.c')
libver = '1.0'
h = install_headers('simple.h')
pkgg.generate(
libraries : [lib, '-lz'],
subdirs : '.',
version : libver,
name : 'libsimple',
filebase : 'simple',
description : 'A simple demo library.',
variables : [ 'key=' ]
)

@ -0,0 +1,5 @@
#include"simple.h"
int simple_function() {
return 42;
}

@ -0,0 +1,6 @@
#ifndef SIMPLE_H_
#define SIMPLE_H_
int simple_function();
#endif

@ -0,0 +1,16 @@
project('variables-not-key-value-test', 'c', version : '1.0')
pkgg = import('pkgconfig')
lib = shared_library('simple', 'simple.c')
libver = '1.0'
h = install_headers('simple.h')
pkgg.generate(
libraries : [lib, '-lz'],
subdirs : '.',
version : libver,
name : 'libsimple',
filebase : 'simple',
description : 'A simple demo library.',
variables : [ 'this_should_be_key_value' ]
)

@ -0,0 +1,5 @@
#include"simple.h"
int simple_function() {
return 42;
}

@ -0,0 +1,6 @@
#ifndef SIMPLE_H_
#define SIMPLE_H_
int simple_function();
#endif
Loading…
Cancel
Save