pkg-config: support for `-l:libfoo.a`

fixs: #9000 Meson not correctly process with -l:xxx.a link arguments in pkgconfig .pc file.

see also:https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a

with unit test, unit test will be partially skiped if pkg-config version < 0.28 .
    see: https://gitlab.freedesktop.org/pkg-config/pkg-config/-/blob/master/NEWS
pull/9082/head
lilinzhe 4 years ago committed by Daniel Mensinger
parent 5c87167a34
commit dd2e3bf446
  1. 24
      mesonbuild/dependencies/pkgconfig.py
  2. 5
      test cases/unit/97 link full name/.gitignore
  3. 20
      test cases/unit/97 link full name/libtestprovider/meson.build
  4. 12
      test cases/unit/97 link full name/libtestprovider/provider.c
  5. 11
      test cases/unit/97 link full name/proguser/meson.build
  6. 19
      test cases/unit/97 link full name/proguser/receiver.c
  7. 43
      unittests/linuxliketests.py

@ -276,6 +276,30 @@ class PkgConfigDependency(ExternalDependency):
elif lib.startswith('-L'):
# We already handled library paths above
continue
elif lib.startswith('-l:'):
# see: https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a
# also : See the documentation of -lnamespec | --library=namespec in the linker manual
# https://sourceware.org/binutils/docs-2.18/ld/Options.html
# Don't resolve the same -l:libfoo.a argument again
if lib in libs_found:
continue
libfilename = lib[3:]
foundname = None
for libdir in libpaths:
target = os.path.join(libdir, libfilename)
if os.path.exists(target):
foundname = target
break
if foundname is None:
if lib in libs_notfound:
continue
else:
mlog.warning('Library {!r} not found for dependency {!r}, may '
'not be successfully linked'.format(libfilename, self.name))
libs_notfound.append(lib)
else:
lib = foundname
elif lib.startswith('-l'):
# Don't resolve the same -lfoo argument again
if lib in libs_found:

@ -0,0 +1,5 @@
*.a
*.o
a.out
libtestprovider.a
build

@ -0,0 +1,20 @@
project('libtestprovider','c')
libtestprovider=static_library('testprovider',
files('./provider.c'),
install:true,
c_args:['-Wall','-Werror'],
)
pkg = import('pkgconfig')
pkg.generate(
name:'testprovider',
filebase:'libtestprovider',
description: 'fortest',
requires: [],
libraries_private: ['-Wl,--whole-archive'] +
['-L${libdir}','-l:libtestprovider.a']+
['-Wl,--no-whole-archive']
)

@ -0,0 +1,12 @@
#include <stdio.h>
static int g_checked = 0;
static void __attribute__((constructor(101), used)) init_checked(void) {
g_checked=100;
fprintf(stdout, "inited\n");
}
int get_checked(void) {
return g_checked;
}

@ -0,0 +1,11 @@
project('testprovider','c')
deplib = dependency('libtestprovider', static:true)
dprovidertest = executable('dprovidertest',
files('./receiver.c'),
dependencies:[deplib],
c_args:['-Wall','-Werror'],
)
test('testprovider',dprovidertest)

@ -0,0 +1,19 @@
#include <stdio.h>
int __attribute__((weak)) get_checked(void) {
return -1;
}
#define CHECK_VALUE (100)
#define TEST_SUCCESS (0)
#define TEST_FAILTURE (-1)
int main(void) {
if (get_checked() == CHECK_VALUE) {
fprintf(stdout,"good\n");
return TEST_SUCCESS;
}
fprintf(stdout,"bad\n");
return TEST_FAILTURE;
}

@ -1297,6 +1297,49 @@ class LinuxlikeTests(BasePlatformTests):
out = self._run(['otool', '-L', f])
# Ensure that the otool output does not contain self.installdir
self.assertNotRegex(out, self.installdir + '.*dylib ')
@skipIfNoPkgconfig
def test_link_arg_fullname(self):
'''
Test for support of -l:libfullname.a
see: https://github.com/mesonbuild/meson/issues/9000
https://stackoverflow.com/questions/48532868/gcc-library-option-with-a-colon-llibevent-a
'''
testdir = os.path.join(self.unit_test_dir, '97 link full name','libtestprovider')
oldprefix = self.prefix
# install into installdir without using DESTDIR
installdir = self.installdir
self.prefix = installdir
self.init(testdir)
self.prefix=oldprefix
self.build()
self.install(use_destdir=False)
self.new_builddir()
env = {'LIBRARY_PATH': os.path.join(installdir, self.libdir),
'PKG_CONFIG_PATH': os.path.join(installdir, self.libdir, 'pkgconfig')}
testdir = os.path.join(self.unit_test_dir, '97 link full name','proguser')
self.init(testdir,override_envvars=env)
# test for link with full path
with open(os.path.join(self.builddir, 'build.ninja'), encoding='utf-8') as bfile:
for line in bfile:
if 'build dprovidertest:' in line:
self.assertIn('/libtestprovider.a', line)
if is_osx():
# macOS's ld do not supports `--whole-archive`, skip build & run
return
self.build(override_envvars=env)
# skip test if pkg-config is too old.
# before v0.28, Libs flags like -Wl will not kept in context order with -l flags.
# see https://gitlab.freedesktop.org/pkg-config/pkg-config/-/blob/master/NEWS
pkgconfigver = subprocess.check_output(['pkg-config', '--version'])
if b'0.28' > pkgconfigver:
raise SkipTest('pkg-config is too old to be correctly done this.')
self.run_tests()
@skipIfNoPkgconfig
def test_usage_pkgconfig_prefixes(self):

Loading…
Cancel
Save