Merge pull request #2611 from mesonbuild/nirbheek/pkgconfig-msvc-static
Several fixes to pkg-config dependencies and the pkg-config module (try 3)
This commit is contained in:
commit
e51da1a34d
|
@ -89,6 +89,8 @@ install:
|
|||
# but they have a broken certificate (on Windows) and an HSTS policy that
|
||||
# forces usage of HTTPS, so we mirror our own copy.
|
||||
- ps: If($Env:compiler -eq 'msys2-mingw') {(new-object Net.WebClient).DownloadFile('https://nirbheek.in/files/meson/get-pip.py', 'C:\projects\meson\get-pip.py')}
|
||||
# pkg-config is needed for the pkg-config tests on msvc
|
||||
- ps: If($Env:compiler.StartsWith('msvc')) {(new-object net.webclient).DownloadFile('http://nirbheek.in/files/binaries/pkg-config/win32/pkg-config.exe', 'C:\projects\meson\pkg-config.exe')}
|
||||
- cmd: if %compiler%==msys2-mingw ( %PYTHON% "C:\projects\meson\get-pip.py" )
|
||||
- cmd: if %compiler%==cygwin ( call ci\appveyor-install.bat )
|
||||
- ps: |
|
||||
|
|
|
@ -22,7 +22,7 @@ from . import mlog
|
|||
from .mesonlib import File, MesonException, listify, extract_as_list
|
||||
from .mesonlib import typeslistify, stringlistify, classify_unity_sources
|
||||
from .mesonlib import get_filenames_templates_dict, substitute_values
|
||||
from .environment import for_windows, for_darwin, for_cygwin
|
||||
from .mesonlib import for_windows, for_darwin, for_cygwin
|
||||
from .compilers import is_object, clike_langs, sort_clike, lang_suffixes
|
||||
|
||||
known_basic_kwargs = {'install': True,
|
||||
|
|
|
@ -17,6 +17,7 @@ import subprocess, os.path, tempfile
|
|||
from .. import mlog
|
||||
from .. import coredata
|
||||
from ..mesonlib import EnvironmentException, version_compare, Popen_safe, listify
|
||||
from ..mesonlib import for_windows, for_darwin, for_cygwin
|
||||
|
||||
from .compilers import (
|
||||
GCC_MINGW,
|
||||
|
@ -710,7 +711,45 @@ class CCompiler(Compiler):
|
|||
return False
|
||||
raise RuntimeError('BUG: {!r} check failed unexpectedly'.format(n))
|
||||
|
||||
def find_library(self, libname, env, extra_dirs):
|
||||
def get_library_naming(self, env, libtype):
|
||||
'''
|
||||
Get library prefixes and suffixes for the target platform ordered by
|
||||
priority
|
||||
'''
|
||||
stlibext = ['a']
|
||||
# We've always allowed libname to be both `foo` and `libfoo`,
|
||||
# and now people depend on it
|
||||
prefixes = ['lib', '']
|
||||
# Library suffixes and prefixes
|
||||
if for_darwin(env.is_cross_build(), env):
|
||||
shlibext = ['dylib']
|
||||
elif for_windows(env.is_cross_build(), env):
|
||||
if self.id == 'msvc':
|
||||
shlibext = ['lib']
|
||||
else:
|
||||
shlibext = ['dll', 'dll.a', 'lib']
|
||||
# Yep, static libraries can also be foo.lib
|
||||
stlibext += ['lib']
|
||||
elif for_cygwin(env.is_cross_build(), env):
|
||||
shlibext = ['dll', 'dll.a']
|
||||
prefixes = ['cyg'] + prefixes
|
||||
else:
|
||||
# Linux/BSDs
|
||||
shlibext = ['so']
|
||||
# Search priority
|
||||
if libtype in ('default', 'shared-static'):
|
||||
suffixes = shlibext + stlibext
|
||||
elif libtype == 'static-shared':
|
||||
suffixes = stlibext + shlibext
|
||||
elif libtype == 'shared':
|
||||
suffixes = shlibext
|
||||
elif libtype == 'static':
|
||||
suffixes = stlibext
|
||||
else:
|
||||
raise AssertionError('BUG: unknown libtype {!r}'.format(libtype))
|
||||
return prefixes, suffixes
|
||||
|
||||
def find_library(self, libname, env, extra_dirs, libtype='default'):
|
||||
# These libraries are either built-in or invalid
|
||||
if libname in self.ignore_libs:
|
||||
return []
|
||||
|
@ -720,21 +759,21 @@ class CCompiler(Compiler):
|
|||
extra_dirs = [extra_dirs]
|
||||
# Gcc + co seem to prefer builtin lib dirs to -L dirs.
|
||||
# Only try to find std libs if no extra dirs specified.
|
||||
if not extra_dirs:
|
||||
if not extra_dirs and libtype == 'default':
|
||||
args = ['-l' + libname]
|
||||
if self.links(code, env, extra_args=args):
|
||||
return args
|
||||
# Not found? Try to find the library file itself.
|
||||
# Not found or we want to use a specific libtype? Try to find the
|
||||
# library file itself.
|
||||
extra_dirs += self.get_library_dirs()
|
||||
suffixes = ['so', 'dylib', 'lib', 'dll', 'a']
|
||||
prefixes, suffixes = self.get_library_naming(env, libtype)
|
||||
# Triply-nested loop!
|
||||
for d in extra_dirs:
|
||||
for suffix in suffixes:
|
||||
trial = os.path.join(d, 'lib' + libname + '.' + suffix)
|
||||
if os.path.isfile(trial):
|
||||
return [trial]
|
||||
trial2 = os.path.join(d, libname + '.' + suffix)
|
||||
if os.path.isfile(trial2):
|
||||
return [trial2]
|
||||
for prefix in prefixes:
|
||||
trial = os.path.join(d, prefix + libname + '.' + suffix)
|
||||
if os.path.isfile(trial):
|
||||
return [trial]
|
||||
return None
|
||||
|
||||
def thread_flags(self):
|
||||
|
|
|
@ -16,9 +16,10 @@
|
|||
# Custom logic for several other packages are in separate files.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
import sys
|
||||
import stat
|
||||
import shlex
|
||||
import shutil
|
||||
from enum import Enum
|
||||
|
||||
from .. import mlog
|
||||
|
@ -258,8 +259,10 @@ class PkgConfigDependency(ExternalDependency):
|
|||
return s.format(self.__class__.__name__, self.name, self.is_found,
|
||||
self.version_reqs)
|
||||
|
||||
def _call_pkgbin(self, args):
|
||||
p, out = Popen_safe([self.pkgbin] + args, env=os.environ)[0:2]
|
||||
def _call_pkgbin(self, args, env=None):
|
||||
if not env:
|
||||
env = os.environ
|
||||
p, out = Popen_safe([self.pkgbin] + args, env=env)[0:2]
|
||||
return p.returncode, out.strip()
|
||||
|
||||
def _set_cargs(self):
|
||||
|
@ -267,19 +270,39 @@ class PkgConfigDependency(ExternalDependency):
|
|||
if ret != 0:
|
||||
raise DependencyException('Could not generate cargs for %s:\n\n%s' %
|
||||
(self.name, out))
|
||||
self.compile_args = out.split()
|
||||
self.compile_args = shlex.split(out)
|
||||
|
||||
def _set_libs(self):
|
||||
env = None
|
||||
libcmd = [self.name, '--libs']
|
||||
if self.static:
|
||||
libcmd.append('--static')
|
||||
ret, out = self._call_pkgbin(libcmd)
|
||||
# Force pkg-config to output -L fields even if they are system
|
||||
# paths so we can do manual searching with cc.find_library() later.
|
||||
env = os.environ.copy()
|
||||
env['PKG_CONFIG_ALLOW_SYSTEM_LIBS'] = '1'
|
||||
ret, out = self._call_pkgbin(libcmd, env=env)
|
||||
if ret != 0:
|
||||
raise DependencyException('Could not generate libs for %s:\n\n%s' %
|
||||
(self.name, out))
|
||||
self.link_args = []
|
||||
for lib in out.split():
|
||||
if lib.endswith(".la"):
|
||||
libpaths = []
|
||||
for lib in shlex.split(out):
|
||||
# If we want to use only static libraries, we have to look for the
|
||||
# file ourselves instead of depending on the compiler to find it
|
||||
# with -lfoo or foo.lib. However, we can only do this if we already
|
||||
# have some library paths gathered.
|
||||
if self.static:
|
||||
if lib.startswith('-L'):
|
||||
libpaths.append(lib[2:])
|
||||
continue
|
||||
elif lib.startswith('-l') and libpaths:
|
||||
args = self.compiler.find_library(lib[2:], self.env, libpaths, libtype='static')
|
||||
if not args or len(args) < 1:
|
||||
raise DependencyException('Static library not found for {!r}'
|
||||
''.format(lib[2:]))
|
||||
lib = args[0]
|
||||
elif lib.endswith(".la"):
|
||||
shared_libname = self.extract_libtool_shlib(lib)
|
||||
shared_lib = os.path.join(os.path.dirname(lib), shared_libname)
|
||||
if not os.path.exists(shared_lib):
|
||||
|
|
|
@ -23,8 +23,9 @@ from collections import OrderedDict
|
|||
|
||||
from .. import mlog
|
||||
from .. import mesonlib
|
||||
from ..mesonlib import MesonException, Popen_safe, version_compare, extract_as_list
|
||||
from ..environment import for_windows, detect_cpu
|
||||
from ..mesonlib import MesonException, Popen_safe, version_compare
|
||||
from ..mesonlib import extract_as_list, for_windows
|
||||
from ..environment import detect_cpu
|
||||
|
||||
from .base import DependencyException, DependencyMethods
|
||||
from .base import ExternalDependency, ExternalProgram
|
||||
|
|
|
@ -219,46 +219,6 @@ def detect_system():
|
|||
return 'cygwin'
|
||||
return system
|
||||
|
||||
|
||||
def for_windows(is_cross, env):
|
||||
"""
|
||||
Host machine is windows?
|
||||
|
||||
Note: 'host' is the machine on which compiled binaries will run
|
||||
"""
|
||||
if not is_cross:
|
||||
return mesonlib.is_windows()
|
||||
elif env.cross_info.has_host():
|
||||
return env.cross_info.config['host_machine']['system'] == 'windows'
|
||||
return False
|
||||
|
||||
|
||||
def for_cygwin(is_cross, env):
|
||||
"""
|
||||
Host machine is cygwin?
|
||||
|
||||
Note: 'host' is the machine on which compiled binaries will run
|
||||
"""
|
||||
if not is_cross:
|
||||
return mesonlib.is_cygwin()
|
||||
elif env.cross_info.has_host():
|
||||
return env.cross_info.config['host_machine']['system'] == 'cygwin'
|
||||
return False
|
||||
|
||||
|
||||
def for_darwin(is_cross, env):
|
||||
"""
|
||||
Host machine is Darwin (iOS/OS X)?
|
||||
|
||||
Note: 'host' is the machine on which compiled binaries will run
|
||||
"""
|
||||
if not is_cross:
|
||||
return mesonlib.is_osx()
|
||||
elif env.cross_info.has_host():
|
||||
return env.cross_info.config['host_machine']['system'] == 'darwin'
|
||||
return False
|
||||
|
||||
|
||||
def search_version(text):
|
||||
# Usually of the type 4.1.4 but compiler output may contain
|
||||
# stuff like this:
|
||||
|
@ -550,9 +510,9 @@ class Environment:
|
|||
cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
|
||||
return cls(ccache + compiler, version, gtype, is_cross, exe_wrap, defines)
|
||||
if 'clang' in out:
|
||||
if 'Apple' in out or for_darwin(want_cross, self):
|
||||
if 'Apple' in out or mesonlib.for_darwin(want_cross, self):
|
||||
cltype = CLANG_OSX
|
||||
elif 'windows' in out or for_windows(want_cross, self):
|
||||
elif 'windows' in out or mesonlib.for_windows(want_cross, self):
|
||||
cltype = CLANG_WIN
|
||||
else:
|
||||
cltype = CLANG_STANDARD
|
||||
|
|
|
@ -219,6 +219,42 @@ def is_cygwin():
|
|||
def is_debianlike():
|
||||
return os.path.isfile('/etc/debian_version')
|
||||
|
||||
def for_windows(is_cross, env):
|
||||
"""
|
||||
Host machine is windows?
|
||||
|
||||
Note: 'host' is the machine on which compiled binaries will run
|
||||
"""
|
||||
if not is_cross:
|
||||
return is_windows()
|
||||
elif env.cross_info.has_host():
|
||||
return env.cross_info.config['host_machine']['system'] == 'windows'
|
||||
return False
|
||||
|
||||
def for_cygwin(is_cross, env):
|
||||
"""
|
||||
Host machine is cygwin?
|
||||
|
||||
Note: 'host' is the machine on which compiled binaries will run
|
||||
"""
|
||||
if not is_cross:
|
||||
return is_cygwin()
|
||||
elif env.cross_info.has_host():
|
||||
return env.cross_info.config['host_machine']['system'] == 'cygwin'
|
||||
return False
|
||||
|
||||
def for_darwin(is_cross, env):
|
||||
"""
|
||||
Host machine is Darwin (iOS/OS X)?
|
||||
|
||||
Note: 'host' is the machine on which compiled binaries will run
|
||||
"""
|
||||
if not is_cross:
|
||||
return is_osx()
|
||||
elif env.cross_info.has_host():
|
||||
return env.cross_info.config['host_machine']['system'] == 'darwin'
|
||||
return False
|
||||
|
||||
def exe_exists(arglist):
|
||||
try:
|
||||
p = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
import os
|
||||
from pathlib import PurePath
|
||||
|
||||
from .. import build
|
||||
from .. import mesonlib
|
||||
|
@ -42,20 +43,34 @@ class PkgConfigModule(ExtensionModule):
|
|||
mlog.warning(msg.format(l.name, 'name_prefix', l.name, pcfile))
|
||||
return l.name
|
||||
|
||||
def _escape(self, value):
|
||||
'''
|
||||
We cannot use shlex.quote because it quotes with ' and " which does not
|
||||
work with pkg-config and pkgconf at all.
|
||||
'''
|
||||
# We should always write out paths with / because pkg-config requires
|
||||
# spaces to be quoted with \ and that messes up on Windows:
|
||||
# https://bugs.freedesktop.org/show_bug.cgi?id=103203
|
||||
if isinstance(value, PurePath):
|
||||
value = value.as_posix()
|
||||
return value.replace(' ', '\ ')
|
||||
|
||||
def generate_pkgconfig_file(self, state, libraries, subdirs, name, description,
|
||||
url, version, pcfile, pub_reqs, priv_reqs,
|
||||
conflicts, priv_libs, extra_cflags, variables):
|
||||
coredata = state.environment.get_coredata()
|
||||
outdir = state.environment.scratch_dir
|
||||
fname = os.path.join(outdir, pcfile)
|
||||
prefix = PurePath(coredata.get_builtin_option('prefix'))
|
||||
# These always return paths relative to prefix
|
||||
libdir = PurePath(coredata.get_builtin_option('libdir'))
|
||||
incdir = PurePath(coredata.get_builtin_option('includedir'))
|
||||
with open(fname, 'w') as ofile:
|
||||
ofile.write('prefix=%s\n' % coredata.get_builtin_option('prefix'))
|
||||
# '${prefix}' is ignored if the second path is absolute (see
|
||||
# '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')))
|
||||
ofile.write('prefix={}\n'.format(self._escape(prefix)))
|
||||
ofile.write('libdir={}\n'.format(self._escape('${prefix}' / libdir)))
|
||||
ofile.write('includedir={}\n'.format(self._escape('${prefix}' / incdir)))
|
||||
for k, v in variables:
|
||||
ofile.write('%s=%s\n' % (k, v))
|
||||
ofile.write('{}={}\n'.format(k, self._escape(v)))
|
||||
ofile.write('\n')
|
||||
ofile.write('Name: %s\n' % name)
|
||||
if len(description) > 0:
|
||||
|
@ -83,7 +98,7 @@ class PkgConfigModule(ExtensionModule):
|
|||
if install_dir is False:
|
||||
continue
|
||||
if isinstance(install_dir, str):
|
||||
yield '-L${prefix}/%s ' % install_dir
|
||||
yield '-L${prefix}/%s ' % self._escape(install_dir)
|
||||
else: # install_dir is True
|
||||
yield '-L${libdir}'
|
||||
lname = self._get_lname(l, msg, pcfile)
|
||||
|
@ -103,10 +118,10 @@ class PkgConfigModule(ExtensionModule):
|
|||
if h == '.':
|
||||
ofile.write('-I${includedir}')
|
||||
else:
|
||||
ofile.write(os.path.join('-I${includedir}', h))
|
||||
ofile.write(self._escape(PurePath('-I${includedir}') / h))
|
||||
for f in extra_cflags:
|
||||
ofile.write(' ')
|
||||
ofile.write(f)
|
||||
ofile.write(self._escape(f))
|
||||
ofile.write('\n')
|
||||
|
||||
def process_libs(self, libs):
|
||||
|
|
171
run_unittests.py
171
run_unittests.py
|
@ -1389,34 +1389,34 @@ int main(int argc, char **argv) {
|
|||
self.assertPathExists(os.path.join(testdir, i))
|
||||
|
||||
def detect_prebuild_env(self):
|
||||
env = Environment('', self.builddir, self.meson_command,
|
||||
get_fake_options(self.prefix), [])
|
||||
cc = env.detect_c_compiler(False)
|
||||
if mesonbuild.mesonlib.is_windows():
|
||||
object_suffix = 'obj'
|
||||
shared_suffix = 'dll'
|
||||
elif mesonbuild.mesonlib.is_cygwin():
|
||||
object_suffix = 'o'
|
||||
shared_suffix = 'dll'
|
||||
elif mesonbuild.mesonlib.is_osx():
|
||||
object_suffix = 'o'
|
||||
shared_suffix = 'dylib'
|
||||
else:
|
||||
object_suffix = 'o'
|
||||
static_suffix = 'a'
|
||||
shared_suffix = 'so'
|
||||
if shutil.which('cl'):
|
||||
compiler = 'cl'
|
||||
static_suffix = 'lib'
|
||||
shared_suffix = 'dll'
|
||||
elif shutil.which('cc'):
|
||||
compiler = 'cc'
|
||||
elif shutil.which('gcc'):
|
||||
compiler = 'gcc'
|
||||
else:
|
||||
raise RuntimeError("Could not find C compiler.")
|
||||
return (compiler, object_suffix, static_suffix, shared_suffix)
|
||||
shared_suffix = 'so'
|
||||
return (cc, object_suffix, shared_suffix)
|
||||
|
||||
def pbcompile(self, compiler, source, objectfile, extra_args=[]):
|
||||
if compiler == 'cl':
|
||||
cmd = [compiler, '/nologo', '/Fo' + objectfile, '/c', source] + extra_args
|
||||
cmd = compiler.get_exelist()
|
||||
if compiler.id == 'msvc':
|
||||
cmd += ['/nologo', '/Fo' + objectfile, '/c', source] + extra_args
|
||||
else:
|
||||
cmd = [compiler, '-c', source, '-o', objectfile] + extra_args
|
||||
cmd += ['-c', source, '-o', objectfile] + extra_args
|
||||
subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
|
||||
def test_prebuilt_object(self):
|
||||
(compiler, object_suffix, _, _) = self.detect_prebuild_env()
|
||||
(compiler, object_suffix, _) = self.detect_prebuild_env()
|
||||
tdir = os.path.join(self.unit_test_dir, '14 prebuilt object')
|
||||
source = os.path.join(tdir, 'source.c')
|
||||
objectfile = os.path.join(tdir, 'prebuilt.' + object_suffix)
|
||||
|
@ -1428,21 +1428,27 @@ int main(int argc, char **argv) {
|
|||
finally:
|
||||
os.unlink(objectfile)
|
||||
|
||||
def test_prebuilt_static_lib(self):
|
||||
(compiler, object_suffix, static_suffix, _) = self.detect_prebuild_env()
|
||||
tdir = os.path.join(self.unit_test_dir, '15 prebuilt static')
|
||||
source = os.path.join(tdir, 'libdir/best.c')
|
||||
objectfile = os.path.join(tdir, 'libdir/best.' + object_suffix)
|
||||
stlibfile = os.path.join(tdir, 'libdir/libbest.' + static_suffix)
|
||||
if compiler == 'cl':
|
||||
link_cmd = ['lib', '/NOLOGO', '/OUT:' + stlibfile, objectfile]
|
||||
def build_static_lib(self, compiler, source, objectfile, outfile, extra_args=None):
|
||||
if extra_args is None:
|
||||
extra_args = []
|
||||
if compiler.id == 'msvc':
|
||||
link_cmd = ['lib', '/NOLOGO', '/OUT:' + outfile, objectfile]
|
||||
else:
|
||||
link_cmd = ['ar', 'csr', stlibfile, objectfile]
|
||||
self.pbcompile(compiler, source, objectfile)
|
||||
link_cmd = ['ar', 'csr', outfile, objectfile]
|
||||
self.pbcompile(compiler, source, objectfile, extra_args=extra_args)
|
||||
try:
|
||||
subprocess.check_call(link_cmd)
|
||||
finally:
|
||||
os.unlink(objectfile)
|
||||
|
||||
def test_prebuilt_static_lib(self):
|
||||
(cc, object_suffix, _) = self.detect_prebuild_env()
|
||||
tdir = os.path.join(self.unit_test_dir, '15 prebuilt static')
|
||||
source = os.path.join(tdir, 'libdir/best.c')
|
||||
objectfile = os.path.join(tdir, 'libdir/best.' + object_suffix)
|
||||
stlibfile = os.path.join(tdir, 'libdir/libbest.a')
|
||||
self.build_static_lib(cc, source, objectfile, stlibfile)
|
||||
# Run the test
|
||||
try:
|
||||
self.init(tdir)
|
||||
self.build()
|
||||
|
@ -1450,26 +1456,37 @@ int main(int argc, char **argv) {
|
|||
finally:
|
||||
os.unlink(stlibfile)
|
||||
|
||||
def test_prebuilt_shared_lib(self):
|
||||
(compiler, object_suffix, _, shared_suffix) = self.detect_prebuild_env()
|
||||
tdir = os.path.join(self.unit_test_dir, '16 prebuilt shared')
|
||||
source = os.path.join(tdir, 'alexandria.c')
|
||||
objectfile = os.path.join(tdir, 'alexandria.' + object_suffix)
|
||||
if compiler == 'cl':
|
||||
def build_shared_lib(self, compiler, source, objectfile, outfile, impfile, extra_args=None):
|
||||
if extra_args is None:
|
||||
extra_args = []
|
||||
shlibfile = os.path.join(tdir, 'alexandria.' + shared_suffix)
|
||||
link_cmd = ['link', '/NOLOGO','/DLL', '/DEBUG', '/IMPLIB:' + os.path.join(tdir, 'alexandria.lib'), '/OUT:' + shlibfile, objectfile]
|
||||
if compiler.id == 'msvc':
|
||||
link_cmd = ['link', '/NOLOGO', '/DLL', '/DEBUG',
|
||||
'/IMPLIB:' + impfile, '/OUT:' + outfile, objectfile]
|
||||
else:
|
||||
extra_args = ['-fPIC']
|
||||
shlibfile = os.path.join(tdir, 'libalexandria.' + shared_suffix)
|
||||
link_cmd = [compiler, '-shared', '-o', shlibfile, objectfile]
|
||||
extra_args += ['-fPIC']
|
||||
link_cmd = compiler.get_exelist() + ['-shared', '-o', outfile, objectfile]
|
||||
if not mesonbuild.mesonlib.is_osx():
|
||||
link_cmd += ['-Wl,-soname=libalexandria.so']
|
||||
link_cmd += ['-Wl,-soname=' + os.path.basename(outfile)]
|
||||
self.pbcompile(compiler, source, objectfile, extra_args=extra_args)
|
||||
try:
|
||||
subprocess.check_call(link_cmd)
|
||||
finally:
|
||||
os.unlink(objectfile)
|
||||
|
||||
def test_prebuilt_shared_lib(self):
|
||||
(cc, object_suffix, shared_suffix) = self.detect_prebuild_env()
|
||||
tdir = os.path.join(self.unit_test_dir, '16 prebuilt shared')
|
||||
source = os.path.join(tdir, 'alexandria.c')
|
||||
objectfile = os.path.join(tdir, 'alexandria.' + object_suffix)
|
||||
impfile = os.path.join(tdir, 'alexandria.lib')
|
||||
if cc.id == 'msvc':
|
||||
shlibfile = os.path.join(tdir, 'alexandria.' + shared_suffix)
|
||||
elif is_cygwin():
|
||||
shlibfile = os.path.join(tdir, 'cygalexandria.' + shared_suffix)
|
||||
else:
|
||||
shlibfile = os.path.join(tdir, 'libalexandria.' + shared_suffix)
|
||||
self.build_shared_lib(cc, source, objectfile, shlibfile, impfile)
|
||||
# Run the test
|
||||
try:
|
||||
self.init(tdir)
|
||||
self.build()
|
||||
|
@ -1483,6 +1500,68 @@ int main(int argc, char **argv) {
|
|||
if os.path.splitext(fname)[1] not in ['.c', '.h']:
|
||||
os.unlink(fname)
|
||||
|
||||
def test_pkgconfig_static(self):
|
||||
'''
|
||||
Test that the we only use static libraries when `static: true` is
|
||||
passed to dependency() with pkg-config. Can't be an ordinary test
|
||||
because we need to build libs and try to find them from meson.build
|
||||
'''
|
||||
if not shutil.which('pkg-config'):
|
||||
raise unittest.SkipTest('pkg-config not found')
|
||||
(cc, objext, shext) = self.detect_prebuild_env()
|
||||
testdir = os.path.join(self.unit_test_dir, '17 pkgconfig static')
|
||||
source = os.path.join(testdir, 'foo.c')
|
||||
objectfile = os.path.join(testdir, 'foo.' + objext)
|
||||
stlibfile = os.path.join(testdir, 'libfoo.a')
|
||||
impfile = os.path.join(testdir, 'foo.lib')
|
||||
if cc.id == 'msvc':
|
||||
shlibfile = os.path.join(testdir, 'foo.' + shext)
|
||||
elif is_cygwin():
|
||||
shlibfile = os.path.join(testdir, 'cygfoo.' + shext)
|
||||
else:
|
||||
shlibfile = os.path.join(testdir, 'libfoo.' + shext)
|
||||
# Build libs
|
||||
self.build_static_lib(cc, source, objectfile, stlibfile, extra_args=['-DFOO_STATIC'])
|
||||
self.build_shared_lib(cc, source, objectfile, shlibfile, impfile)
|
||||
# Run test
|
||||
os.environ['PKG_CONFIG_LIBDIR'] = self.builddir
|
||||
try:
|
||||
self.init(testdir)
|
||||
self.build()
|
||||
self.run_tests()
|
||||
finally:
|
||||
os.unlink(stlibfile)
|
||||
os.unlink(shlibfile)
|
||||
if mesonbuild.mesonlib.is_windows():
|
||||
# Clean up all the garbage MSVC writes in the
|
||||
# source tree.
|
||||
for fname in glob(os.path.join(testdir, 'foo.*')):
|
||||
if os.path.splitext(fname)[1] not in ['.c', '.h', '.in']:
|
||||
os.unlink(fname)
|
||||
|
||||
def test_pkgconfig_gen_escaping(self):
|
||||
if not shutil.which('pkg-config'):
|
||||
raise unittest.SkipTest('pkg-config not found')
|
||||
testdir = os.path.join(self.common_test_dir, '51 pkgconfig-gen')
|
||||
prefix = '/usr/with spaces'
|
||||
libdir = 'lib'
|
||||
self.init(testdir, extra_args=['--prefix=' + prefix,
|
||||
'--libdir=' + libdir])
|
||||
# Find foo dependency
|
||||
os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir
|
||||
env = FakeEnvironment()
|
||||
kwargs = {'required': True, 'silent': True}
|
||||
foo_dep = PkgConfigDependency('libfoo', env, kwargs)
|
||||
# Ensure link_args are properly quoted
|
||||
libdir = PurePath(prefix) / PurePath(libdir)
|
||||
link_args = ['-L' + libdir.as_posix(), '-lfoo']
|
||||
self.assertEqual(foo_dep.get_link_args(), link_args)
|
||||
# Ensure include args are properly quoted
|
||||
incdir = PurePath(prefix) / PurePath('include')
|
||||
cargs = ['-I' + incdir.as_posix()]
|
||||
self.assertEqual(foo_dep.get_compile_args(), cargs)
|
||||
|
||||
|
||||
class FailureTests(BasePlatformTests):
|
||||
'''
|
||||
Tests that test failure conditions. Build files here should be dynamically
|
||||
|
@ -1539,6 +1618,8 @@ class FailureTests(BasePlatformTests):
|
|||
def test_dependency(self):
|
||||
if not shutil.which('pkg-config'):
|
||||
raise unittest.SkipTest('pkg-config not found')
|
||||
if subprocess.call(['pkg-config', '--exists', 'zlib']) != 0:
|
||||
raise unittest.SkipTest('zlib not found with pkg-config')
|
||||
a = (("dependency('zlib', method : 'fail')", "'fail' is invalid"),
|
||||
("dependency('zlib', static : '1')", "[Ss]tatic.*boolean"),
|
||||
("dependency('zlib', version : 1)", "[Vv]ersion.*string or list"),
|
||||
|
@ -1722,12 +1803,12 @@ class LinuxlikeTests(BasePlatformTests):
|
|||
env = FakeEnvironment()
|
||||
kwargs = {'required': True, 'silent': True}
|
||||
os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir
|
||||
simple_dep = PkgConfigDependency('libfoo', env, kwargs)
|
||||
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')
|
||||
foo_dep = PkgConfigDependency('libfoo', env, kwargs)
|
||||
self.assertTrue(foo_dep.found())
|
||||
self.assertEqual(foo_dep.get_version(), '1.0')
|
||||
self.assertIn('-lfoo', foo_dep.get_link_args())
|
||||
self.assertEqual(foo_dep.get_pkgconfig_variable('foo'), 'bar')
|
||||
self.assertPathEqual(foo_dep.get_pkgconfig_variable('datadir'), '/usr/data')
|
||||
|
||||
def test_vala_c_warnings(self):
|
||||
'''
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
int power_level (void)
|
||||
{
|
||||
#ifdef FOO_STATIC
|
||||
return 9001;
|
||||
#else
|
||||
return 8999;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
prefix=@PREFIX@
|
||||
libdir=${prefix}
|
||||
includedir=${prefix}/include
|
||||
datadir=${prefix}/data
|
||||
|
||||
Name: libfoo
|
||||
Description: A foo library.
|
||||
Version: 1.0
|
||||
Libs: -L${libdir} -lfoo
|
||||
Cflags: -I${includedir}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
int power_level (void);
|
|
@ -0,0 +1,14 @@
|
|||
#include <foo.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (int argc, char * argv[])
|
||||
{
|
||||
int value = power_level ();
|
||||
if (value < 9000) {
|
||||
printf ("Power level is %i\n", value);
|
||||
return 1;
|
||||
}
|
||||
printf ("IT'S OVER 9000!!!\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
project('pkg-config static', 'c')
|
||||
|
||||
if build_machine.system() != 'windows'
|
||||
prefix = meson.source_root()
|
||||
else
|
||||
# pkg-config files should not use paths with \
|
||||
prefix_parts = meson.source_root().split('\\')
|
||||
prefix = '/'.join(prefix_parts)
|
||||
endif
|
||||
|
||||
# Escape spaces
|
||||
prefix_parts = prefix.split(' ')
|
||||
prefix = '\ '.join(prefix_parts)
|
||||
|
||||
conf = configuration_data()
|
||||
conf.set('PREFIX', prefix)
|
||||
configure_file(input : 'foo.pc.in',
|
||||
output : 'foo.pc',
|
||||
configuration : conf)
|
||||
|
||||
foo_dep = dependency('foo', static : true)
|
||||
|
||||
test('footest', executable('foomain', 'main.c', dependencies : foo_dep))
|
Loading…
Reference in New Issue