aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2018-10-28 13:27:51 -0400
committerXavier Claessens <xclaesse@gmail.com>2018-12-04 06:49:02 -0500
commit8612f1543f280342fcbff69863b8401319fccc7d (patch)
tree67be598421bb438153993a23f8f46e3a539c1aab
parent377719cc7bc7723d7e3fabce56df35c8aad35a69 (diff)
downloadmeson-8612f1543f280342fcbff69863b8401319fccc7d.zip
meson-8612f1543f280342fcbff69863b8401319fccc7d.tar.gz
meson-8612f1543f280342fcbff69863b8401319fccc7d.tar.bz2
pkgconfig: Improve and document generator behaviour
- Add libraries from InternalDependency.libraries - Deprecate association of libraries from the "libraries" keyword argument to the generated pkg-config file.
-rw-r--r--docs/markdown/Pkgconfig-module.md57
-rw-r--r--docs/markdown/snippets/pkgconfig_break.md34
-rw-r--r--mesonbuild/modules/pkgconfig.py48
-rw-r--r--test cases/common/48 pkgconfig-gen/dependencies/custom.c3
-rw-r--r--test cases/common/48 pkgconfig-gen/dependencies/meson.build3
5 files changed, 126 insertions, 19 deletions
diff --git a/docs/markdown/Pkgconfig-module.md b/docs/markdown/Pkgconfig-module.md
index 9a34e14..6aee0c7 100644
--- a/docs/markdown/Pkgconfig-module.md
+++ b/docs/markdown/Pkgconfig-module.md
@@ -5,9 +5,12 @@ This module is a simple generator for
## Usage
-To use this module, just do: **`pkg = import('pkgconfig')`**. The
-following function will then be available as `pkg.generate()`. You
-can, of course, replace the name `pkg` with anything else.
+```meson
+pkg = import('pkgconfig')
+bar_dep = dependency('bar')
+lib = library('foo', dependencies : [bar])
+pkg.generate(lib)
+```
### pkg.generate()
@@ -25,14 +28,13 @@ keyword arguments.
- `libraries` a list of built libraries (usually results of
shared_library) that the user needs to link against. Arbitrary strings can
also be provided and they will be added into the `Libs` field. Since 0.45.0
- dependencies of built libraries will be automatically added to `Libs.private`
- field. If a dependency is provided by pkg-config then it will be added in
- `Requires.private` instead. Other type of dependency objects can also be passed
- and will result in their `link_args` and `compile_args` to be added to `Libs`
- and `Cflags` fields.
+ dependencies of built libraries will be automatically added, see the
+ [Implicit dependencies](#Implicit_dependencies) section below for the exact
+ rules.
- `libraries_private` list of built libraries or strings to put in the
- `Libs.private` field. Since 0.45.0 it can also contain dependency objects,
- their `link_args` will be added to `Libs.private`.
+ `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.
- `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
@@ -59,3 +61,38 @@ provided for all required fields of the pc file:
- `install_dir` is set to `pkgconfig` folder in the same location than the provided library.
- `description` is set to the project's name followed by the library's name.
- `name` is set to the library's name.
+
+### Implicit dependencies
+
+The exact rules followed to find dependencies that are implicitly added into the
+pkg-config file have evolved over time. Here are the rules as of Meson *0.49.0*,
+previous versions might have slightly different behaviour.
+
+- Not found libraries or dependencies are ignored.
+- Libraries and dependencies are private by default (i.e. added into
+ `Requires.private:` or `Libs.private:`) unless they are explicitly added in
+ `libraries` or `requires` keyword arguments, or is the main library (first
+ positional argument).
+- Libraries and dependencies will be de-duplicated, if they are added in both
+ public and private (e.g `Requires:` and `Requires.private:`) it will be removed
+ from the private list.
+- Shared libraries (i.e. `shared_library()` and **NOT** `library()`) add only
+ `-lfoo` into `Libs:` or `Libs.private:` but their dependencies are not pulled.
+ This is because dependencies are only needed for static link.
+- Other libraries (i.e. `static_library()` or `library()`) add `-lfoo` into `Libs:`
+ or `Libs.private:` and recursively add their dependencies into `Libs.private:` or
+ `Requires.private:`.
+- Dependencies provided by pkg-config are added into `Requires:` or
+ `Requires.private:`. If a version was specified when declaring that dependency
+ it will be written into the generated file too.
+- The thread dependency (i.e. `dependency('thread')`) adds `-pthread` into
+ `Libs:` or `Libs.private:`.
+- Internal dependencies (i.e.
+ `declare_dependency(compiler_args : '-DFOO', link_args : '-Wl,something', link_with : foo)`)
+ add `compiler_args` into `Cflags:` if public, `link_args` and `link_with` into
+ `Libs:` if public or `Libs.private:` if private.
+- Other dependency types add their compiler arguments into `Cflags:` if public,
+ and linker arguments into `Libs:` if public or `Libs.private:` if private.
+- Once a pkg-config file is generated for a library using `pkg.generate(mylib)`,
+ any subsequent call to `pkg.generate()` where mylib appears, will generate a
+ `Requires:` or `Requires.private` instead of a `Libs:` or `Libs.private:`.
diff --git a/docs/markdown/snippets/pkgconfig_break.md b/docs/markdown/snippets/pkgconfig_break.md
new file mode 100644
index 0000000..49c908d
--- /dev/null
+++ b/docs/markdown/snippets/pkgconfig_break.md
@@ -0,0 +1,34 @@
+## Deprecation warning in pkg-config generator
+
+All libraries passed to the `libraries` keyword argument of the `generate()`
+method used to be associated with that generated pkg-config file. That means
+that any subsequent call to `generate()` where those libraries appear would add
+the filebase of the `generate()` that first contained them into `Requires:` or
+`Requires.private:` field instead of adding an `-l` to `Libs:` or `Libs.private:`.
+
+This behaviour is now deprecated. The library that should be associated with
+the generated pkg-config file should be passed as first positional argument
+instead of in the `libraries` keyword argument. The previous behaviour is
+maintained but prints a deprecation warning and support for this will be removed
+in a future Meson release. If you can not create the needed pkg-config file
+without this warning, please file an issue with as much details as possible
+about the situation.
+
+For example this sample will write `Requires: liba` into `libb.pc` but print a
+deprecation warning:
+```meson
+liba = library(...)
+pkg.generate(libraries : liba)
+
+libb = library(...)
+pkg.generate(libraries : [liba, libb])
+```
+
+It can be fixed by passing `liba` as first positional argument::
+```meson
+liba = library(...)
+pkg.generate(liba)
+
+libb = library(...)
+pkg.generate(libb, libraries : [liba])
+```
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 708695a..eee3783 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import os
+import os, types
from pathlib import PurePath
from .. import build
@@ -50,11 +50,24 @@ class DependenciesHelper:
def add_priv_reqs(self, reqs):
self.priv_reqs += self._process_reqs(reqs)
+ def _check_generated_pc_deprecation(self, obj):
+ if hasattr(obj, 'generated_pc_warn'):
+ mlog.deprecation('Library', mlog.bold(obj.name), 'was passed to the '
+ '"libraries" keyword argument of a previous call '
+ 'to generate() method instead of first positional '
+ 'argument.', 'Adding', mlog.bold(obj.generated_pc),
+ 'to "Requires" field, but this is a deprecated '
+ 'behaviour that will change in a future version '
+ 'of Meson. Please report the issue if this '
+ 'warning cannot be avoided in your case.',
+ location=obj.generated_pc_warn)
+
def _process_reqs(self, reqs):
'''Returns string names of requirements'''
processed_reqs = []
for obj in mesonlib.listify(reqs, unholder=True):
if hasattr(obj, 'generated_pc'):
+ self._check_generated_pc_deprecation(obj)
processed_reqs.append(obj.generated_pc)
elif hasattr(obj, 'pcdep'):
pcdeps = mesonlib.listify(obj.pcdep)
@@ -93,7 +106,8 @@ class DependenciesHelper:
for d in pcdeps:
processed_reqs.append(d.name)
self.add_version_reqs(d.name, obj.version_reqs)
- elif hasattr(obj, 'generated_pc') and obj.generated_pc != self.name:
+ elif hasattr(obj, 'generated_pc'):
+ self._check_generated_pc_deprecation(obj)
processed_reqs.append(obj.generated_pc)
elif isinstance(obj, dependencies.PkgConfigDependency):
if obj.found():
@@ -102,6 +116,14 @@ class DependenciesHelper:
elif isinstance(obj, dependencies.ThreadDependency):
processed_libs += obj.get_compiler().thread_link_flags(obj.env)
processed_cflags += obj.get_compiler().thread_flags(obj.env)
+ elif isinstance(obj, dependencies.InternalDependency):
+ if obj.found():
+ processed_libs += obj.get_link_args()
+ processed_cflags += obj.get_compile_args()
+ if public:
+ self.add_pub_libs(obj.libraries)
+ else:
+ self.add_priv_libs(obj.libraries)
elif isinstance(obj, dependencies.Dependency):
if obj.found():
processed_libs += obj.get_link_args()
@@ -114,14 +136,8 @@ class DependenciesHelper:
# than needed build deps.
# See https://bugs.freedesktop.org/show_bug.cgi?id=105572
processed_libs.append(obj)
- if public:
- if not hasattr(obj, 'generated_pc'):
- obj.generated_pc = self.name
elif isinstance(obj, (build.SharedLibrary, build.StaticLibrary)):
processed_libs.append(obj)
- if public:
- if not hasattr(obj, 'generated_pc'):
- obj.generated_pc = self.name
if isinstance(obj, build.StaticLibrary) and public:
self.add_pub_libs(obj.get_dependencies(internal=False))
self.add_pub_libs(obj.get_external_deps())
@@ -407,6 +423,22 @@ class PkgConfigModule(ExtensionModule):
self.generate_pkgconfig_file(state, deps, subdirs, name, description, url,
version, pcfile, conflicts, variables)
res = build.Data(mesonlib.File(True, state.environment.get_scratch_dir(), pcfile), pkgroot)
+ # Associate the main library with this generated pc file. If the library
+ # is used in any subsequent call to the generated, it will generate a
+ # 'Requires:' or 'Requires.private:'.
+ # Backward compatibility: We used to set 'generated_pc' on all public
+ # libraries instead of just the main one. Keep doing that but warn if
+ # anyone is relying on that deprecated behaviour.
+ if mainlib:
+ if not hasattr(mainlib, 'generated_pc'):
+ mainlib.generated_pc = filebase
+ else:
+ mlog.warning('Already generated a pkg-config file for', mlog.bold(mainlib.name))
+ for lib in deps.pub_libs:
+ if not isinstance(lib, str) and not hasattr(lib, 'generated_pc'):
+ lib.generated_pc = filebase
+ lib.generated_pc_warn = types.SimpleNamespace(subdir=state.subdir,
+ lineno=state.current_lineno)
return ModuleReturnValue(res, [res])
def initialize(*args, **kwargs):
diff --git a/test cases/common/48 pkgconfig-gen/dependencies/custom.c b/test cases/common/48 pkgconfig-gen/dependencies/custom.c
new file mode 100644
index 0000000..2cc5651
--- /dev/null
+++ b/test cases/common/48 pkgconfig-gen/dependencies/custom.c
@@ -0,0 +1,3 @@
+int custom_function() {
+ return 42;
+}
diff --git a/test cases/common/48 pkgconfig-gen/dependencies/meson.build b/test cases/common/48 pkgconfig-gen/dependencies/meson.build
index 047e7e7..2dad393 100644
--- a/test cases/common/48 pkgconfig-gen/dependencies/meson.build
+++ b/test cases/common/48 pkgconfig-gen/dependencies/meson.build
@@ -6,6 +6,7 @@ pkgg = import('pkgconfig')
exposed_lib = shared_library('libexposed', 'exposed.c')
internal_lib = shared_library('libinternal', 'internal.c')
main_lib = both_libraries('libmain', link_with : [exposed_lib, internal_lib])
+custom_lib = shared_library('custom', 'custom.c')
pkgg.generate(exposed_lib)
@@ -14,7 +15,7 @@ pc_dep = dependency('libfoo', version : '>=1.0')
pc_dep_dup = dependency('libfoo', version : '>= 1.0')
notfound_dep = dependency('notfound', required : false)
threads_dep = dependency('threads')
-custom_dep = declare_dependency(link_args : ['-lcustom'], compile_args : ['-DCUSTOM'])
+custom_dep = declare_dependency(link_with : custom_lib, compile_args : ['-DCUSTOM'])
custom2_dep = declare_dependency(link_args : ['-lcustom2'], compile_args : ['-DCUSTOM2'])
# Generate a PC file: