Merge pull request #3251 from mesonbuild/fixpkgconfigdeps

Fix pkg-config dependencies leaking out (debbug 892956)
pull/3273/head
Jussi Pakkanen 7 years ago committed by GitHub
commit e984e1072b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      mesonbuild/modules/pkgconfig.py
  2. 44
      run_unittests.py
  3. 2
      test cases/common/51 pkgconfig-gen/dependencies/meson.build
  4. 7
      test cases/unit/24 pkgconfig usage/dependee/meson.build
  5. 6
      test cases/unit/24 pkgconfig usage/dependee/pkguser.c
  6. 24
      test cases/unit/24 pkgconfig usage/dependency/meson.build
  7. 7
      test cases/unit/24 pkgconfig usage/dependency/pkgdep.c
  8. 3
      test cases/unit/24 pkgconfig usage/dependency/pkgdep.h
  9. 3
      test cases/unit/24 pkgconfig usage/dependency/privatelib.c

@ -96,7 +96,20 @@ class DependenciesHelper:
if obj.found():
processed_libs += obj.get_link_args()
processed_cflags += obj.get_compile_args()
elif isinstance(obj, (build.SharedLibrary, build.StaticLibrary)):
elif isinstance(obj, build.SharedLibrary):
processed_libs.append(obj)
if public:
if not hasattr(obj, 'generated_pc'):
obj.generated_pc = self.name
elif isinstance(obj, build.StaticLibrary):
# Due to a "feature" in pkgconfig, it leaks out private dependencies.
# Thus we will not add them to the pc file unless the target
# we are processing is a static library.
#
# This way (hopefully) "pkgconfig --libs --static foobar" works
# and "pkgconfig --cflags/--libs foobar" does not have any trace
# of dependencies that the build file creator has not explicitly
# added to the dependency list.
processed_libs.append(obj)
if public:
if not hasattr(obj, 'generated_pc'):

@ -513,7 +513,8 @@ class BasePlatformTests(unittest.TestCase):
windows_proof_rmtree(path)
except FileNotFoundError:
pass
os.environ = self.orig_env
os.environ.clear()
os.environ.update(self.orig_env)
super().tearDown()
def _run(self, command, workdir=None):
@ -588,10 +589,11 @@ class BasePlatformTests(unittest.TestCase):
def run_tests(self):
self._run(self.test_command, workdir=self.builddir)
def install(self):
def install(self, *, use_destdir=True):
if self.backend is not Backend.ninja:
raise unittest.SkipTest('{!r} backend can\'t install files'.format(self.backend.name))
os.environ['DESTDIR'] = self.installdir
if use_destdir:
os.environ['DESTDIR'] = self.installdir
self._run(self.install_command, workdir=self.builddir)
def uninstall(self):
@ -2735,6 +2737,42 @@ endian = 'little'
self.build()
mesonbuild.modules.gnome.native_glib_version = None
@unittest.skipIf(shutil.which('pkg-config') is None, 'Pkg-config not found.')
def test_pkgconfig_usage(self):
testdir1 = os.path.join(self.unit_test_dir, '24 pkgconfig usage/dependency')
testdir2 = os.path.join(self.unit_test_dir, '24 pkgconfig usage/dependee')
if subprocess.call(['pkg-config', '--cflags', 'glib-2.0'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL) != 0:
raise unittest.SkipTest('Glib 2.0 dependency not available.')
with tempfile.TemporaryDirectory() as tempdirname:
self.init(testdir1, ['--prefix=' + tempdirname, '--libdir=lib'], default_args=False)
self.install(use_destdir=False)
shutil.rmtree(self.builddir)
os.mkdir(self.builddir)
pkg_dir = os.path.join(tempdirname, 'lib/pkgconfig')
self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'libpkgdep.pc')))
lib_dir = os.path.join(tempdirname, 'lib')
os.environ['PKG_CONFIG_PATH'] = pkg_dir
# Private internal libraries must not leak out.
pkg_out = subprocess.check_output(['pkg-config', '--static', '--libs', 'libpkgdep'])
self.assertFalse(b'libpkgdep-int' in pkg_out, 'Internal library leaked out.')
# Dependencies must not leak to cflags when building only a shared library.
pkg_out = subprocess.check_output(['pkg-config', '--cflags', 'libpkgdep'])
self.assertFalse(b'glib' in pkg_out, 'Internal dependency leaked to headers.')
# Test that the result is usable.
self.init(testdir2)
self.build()
myenv = os.environ.copy()
myenv['LD_LIBRARY_PATH'] = lib_dir
if is_cygwin():
bin_dir = os.path.join(tempdirname, 'bin')
myenv['PATH'] = bin_dir + os.pathsep + myenv['PATH']
self.assertTrue(os.path.isdir(lib_dir))
test_exe = os.path.join(self.builddir, 'pkguser')
self.assertTrue(os.path.isfile(test_exe))
subprocess.check_call(test_exe, env=myenv)
class LinuxArmCrossCompileTests(BasePlatformTests):
'''

@ -5,7 +5,7 @@ pkgg = import('pkgconfig')
# libmain internally use libinternal and expose libexpose in its API
exposed_lib = shared_library('libexposed', 'exposed.c')
internal_lib = shared_library('libinternal', 'internal.c')
main_lib = shared_library('libmain', link_with : [exposed_lib, internal_lib])
main_lib = static_library('libmain', link_with : [exposed_lib, internal_lib])
pkgg.generate(libraries : exposed_lib,
version : '1.0',

@ -0,0 +1,7 @@
project('pkgconfig user', 'c')
pkgdep = dependency('libpkgdep')
executable('pkguser', 'pkguser.c',
dependencies : pkgdep)

@ -0,0 +1,6 @@
#include<pkgdep.h>
int main(int argc, char **argv) {
int res = pkgdep();
return res != 99;
}

@ -0,0 +1,24 @@
project('pkgconfig dep', 'c',
version : '1.0.0')
# This is not used in the code, only to check that it does not
# leak out to --libs.
glib_dep = dependency('glib-2.0')
pkgconfig = import('pkgconfig')
intlib = static_library('libpkgdep-int', 'privatelib.c')
intdep = declare_dependency(link_with : intlib)
lib = shared_library('pkgdep', 'pkgdep.c',
dependencies : [glib_dep, intdep],
install : true)
install_headers('pkgdep.h')
pkgconfig.generate(
filebase : 'libpkgdep',
name : 'Libpkgdep',
description : 'Sample pkgconfig dependency library',
version : meson.project_version(),
libraries : lib)

@ -0,0 +1,7 @@
#include<pkgdep.h>
int internal_thingy();
int pkgdep() {
return internal_thingy();
}

@ -0,0 +1,3 @@
int internal_thingy() {
return 99;
}
Loading…
Cancel
Save