diff options
author | lilinzhe <slayercat.subscription@gmail.com> | 2021-07-19 15:24:44 +0800 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2021-08-10 16:06:45 +0530 |
commit | 596b24ac5b608fac61d29e7d71813838c0b55029 (patch) | |
tree | dbeecddc141880e291c438d0c35a8a92262065a8 | |
parent | af280058b01d7970da9bb8fbad2966f9c72cf6a0 (diff) | |
download | meson-596b24ac5b608fac61d29e7d71813838c0b55029.zip meson-596b24ac5b608fac61d29e7d71813838c0b55029.tar.gz meson-596b24ac5b608fac61d29e7d71813838c0b55029.tar.bz2 |
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
-rw-r--r-- | mesonbuild/dependencies/pkgconfig.py | 24 | ||||
-rwxr-xr-x | run_unittests.py | 43 | ||||
-rw-r--r-- | test cases/unit/97 link full name/.gitignore | 5 | ||||
-rw-r--r-- | test cases/unit/97 link full name/libtestprovider/meson.build | 20 | ||||
-rw-r--r-- | test cases/unit/97 link full name/libtestprovider/provider.c | 12 | ||||
-rw-r--r-- | test cases/unit/97 link full name/proguser/meson.build | 11 | ||||
-rw-r--r-- | test cases/unit/97 link full name/proguser/receiver.c | 19 |
7 files changed, 134 insertions, 0 deletions
diff --git a/mesonbuild/dependencies/pkgconfig.py b/mesonbuild/dependencies/pkgconfig.py index 1e8d913..f097504 100644 --- a/mesonbuild/dependencies/pkgconfig.py +++ b/mesonbuild/dependencies/pkgconfig.py @@ -277,6 +277,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: diff --git a/run_unittests.py b/run_unittests.py index 91f3f3c..9f853d8 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -7956,6 +7956,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 unittest.SkipTest('pkg-config is too old to be correctly done this.') + self.run_tests() @skipIfNoPkgconfig def test_usage_pkgconfig_prefixes(self): diff --git a/test cases/unit/97 link full name/.gitignore b/test cases/unit/97 link full name/.gitignore new file mode 100644 index 0000000..8129601 --- /dev/null +++ b/test cases/unit/97 link full name/.gitignore @@ -0,0 +1,5 @@ +*.a +*.o +a.out +libtestprovider.a +build diff --git a/test cases/unit/97 link full name/libtestprovider/meson.build b/test cases/unit/97 link full name/libtestprovider/meson.build new file mode 100644 index 0000000..5855c81 --- /dev/null +++ b/test cases/unit/97 link full name/libtestprovider/meson.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'] +) diff --git a/test cases/unit/97 link full name/libtestprovider/provider.c b/test cases/unit/97 link full name/libtestprovider/provider.c new file mode 100644 index 0000000..5e79966 --- /dev/null +++ b/test cases/unit/97 link full name/libtestprovider/provider.c @@ -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; +} diff --git a/test cases/unit/97 link full name/proguser/meson.build b/test cases/unit/97 link full name/proguser/meson.build new file mode 100644 index 0000000..5be5bc9 --- /dev/null +++ b/test cases/unit/97 link full name/proguser/meson.build @@ -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) diff --git a/test cases/unit/97 link full name/proguser/receiver.c b/test cases/unit/97 link full name/proguser/receiver.c new file mode 100644 index 0000000..594601c --- /dev/null +++ b/test cases/unit/97 link full name/proguser/receiver.c @@ -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; +} + |