Skip to content

Commit

Permalink
Test that system shlibs with undefined symbols can be found
Browse files Browse the repository at this point in the history
  • Loading branch information
nirbheek committed Aug 19, 2018
1 parent c98156d commit 14f8deb
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 43 deletions.
36 changes: 26 additions & 10 deletions run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,32 @@
from mesonbuild import mesonmain
from mesonbuild import mtest
from mesonbuild import mlog
from mesonbuild.environment import detect_ninja
from mesonbuild.environment import Environment, detect_ninja


# Fake classes and objects for mocking
class FakeBuild:
def __init__(self, env):
self.environment = env

class FakeCompilerOptions:
def __init__(self):
self.value = []

def get_fake_options(prefix):
import argparse
opts = argparse.Namespace()
opts.cross_file = None
opts.wrap_mode = None
opts.prefix = prefix
opts.cmd_line_options = {}
return opts

def get_fake_env(sdir, bdir, prefix):
env = Environment(sdir, bdir, get_fake_options(prefix))
env.coredata.compiler_options['c_args'] = FakeCompilerOptions()
return env


Backend = Enum('Backend', 'ninja vs xcode')

Expand Down Expand Up @@ -148,15 +173,6 @@ def ensure_backend_detects_changes(backend):
if backend is Backend.ninja:
time.sleep(1)

def get_fake_options(prefix):
import argparse
opts = argparse.Namespace()
opts.cross_file = None
opts.wrap_mode = None
opts.prefix = prefix
opts.cmd_line_options = {}
return opts

def run_mtest_inprocess(commandlist):
old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()
Expand Down
51 changes: 22 additions & 29 deletions run_unittests.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,16 @@
windows_proof_rmtree, python_command, version_compare,
grab_leading_numbers, BuildDirLock
)
from mesonbuild.environment import Environment, detect_ninja
from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import MesonException, EnvironmentException
from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
import mesonbuild.modules.pkgconfig

from run_tests import exe_suffix, get_fake_options, get_meson_script
from run_tests import exe_suffix, get_fake_env, get_meson_script
from run_tests import get_builddir_target_args, get_backend_commands, Backend
from run_tests import ensure_backend_detects_changes, run_configure_inprocess
from run_tests import run_mtest_inprocess

# Fake classes for mocking
class FakeBuild:
def __init__(self, env):
self.environment = env

class FakeCompilerOptions:
def __init__(self):
self.value = []
from run_tests import FakeBuild, FakeCompilerOptions

def get_dynamic_section_entry(fname, entry):
if is_cygwin() or is_osx():
Expand Down Expand Up @@ -563,7 +555,7 @@ def test_find_library_patterns(self):
'windows-mingw': {'shared': ['lib{}.dll.a', 'lib{}.lib', 'lib{}.dll',
'{}.dll.a', '{}.lib', '{}.dll'],
'static': msvc_static}}
env = Environment('', '', get_fake_options(''))
env = get_fake_env('', '', '')
cc = env.detect_c_compiler(False)
if is_osx():
self._test_all_naming(cc, env, patterns, 'darwin')
Expand Down Expand Up @@ -606,7 +598,7 @@ def test_pkgconfig_parse_libs(self):
'''
with tempfile.TemporaryDirectory() as tmpdir:
pkgbin = ExternalProgram('pkg-config', command=['pkg-config'], silent=True)
env = Environment('', '', get_fake_options(''))
env = get_fake_env('', '', '')
compiler = env.detect_c_compiler(False)
env.coredata.compilers = {'c': compiler}
env.coredata.compiler_options['c_link_args'] = FakeCompilerOptions()
Expand Down Expand Up @@ -689,7 +681,7 @@ def test_compiler_options_documented(self):
with open('docs/markdown/Builtin-options.md') as f:
md = f.read()
self.assertIsNotNone(md)
env = Environment('', '', get_fake_options(''))
env = get_fake_env('', '', '')
# FIXME: Support other compilers
cc = env.detect_c_compiler(False)
cpp = env.detect_cpp_compiler(False)
Expand Down Expand Up @@ -735,7 +727,7 @@ def test_syntax_highlighting_files(self):
Ensure that syntax highlighting files were updated for new functions in
the global namespace in build files.
'''
env = Environment('', '', get_fake_options(''))
env = get_fake_env('', '', '')
interp = Interpreter(FakeBuild(env), mock=True)
with open('data/syntax-highlighting/vim/syntax/meson.vim') as f:
res = re.search(r'syn keyword mesonBuiltin(\s+\\\s\w+)+', f.read(), re.MULTILINE)
Expand Down Expand Up @@ -1169,7 +1161,7 @@ def test_static_library_overwrite(self):
https://github.com/mesonbuild/meson/issues/1355
'''
testdir = os.path.join(self.common_test_dir, '3 static')
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(False)
static_linker = env.detect_static_linker(cc)
if is_windows():
Expand Down Expand Up @@ -1456,7 +1448,7 @@ def test_compiler_detection(self):
if not is_windows():
langs += [('objc', 'OBJC'), ('objcpp', 'OBJCXX')]
testdir = os.path.join(self.unit_test_dir, '5 compiler detection')
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
for lang, evar in langs:
# Detect with evar and do sanity checks on that
if evar in os.environ:
Expand Down Expand Up @@ -1558,7 +1550,7 @@ def test_compiler_detection(self):
def test_always_prefer_c_compiler_for_asm(self):
testdir = os.path.join(self.common_test_dir, '138 c cpp and asm')
# Skip if building with MSVC
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
if env.detect_c_compiler(False).get_id() == 'msvc':
raise unittest.SkipTest('MSVC can\'t compile assembly')
self.init(testdir)
Expand Down Expand Up @@ -1816,7 +1808,7 @@ def test_all_forbidden_targets_tested(self):
self.assertPathExists(os.path.join(testdir, i))

def detect_prebuild_env(self):
env = Environment('', self.builddir, get_fake_options(self.prefix))
env = get_fake_env('', self.builddir, self.prefix)
cc = env.detect_c_compiler(False)
stlinker = env.detect_static_linker(cc)
if mesonbuild.mesonlib.is_windows():
Expand Down Expand Up @@ -1982,7 +1974,7 @@ def test_pkgconfig_gen_escaping(self):
'--libdir=' + libdir])
# Find foo dependency
os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
kwargs = {'required': True, 'silent': True}
foo_dep = PkgConfigDependency('libfoo', env, kwargs)
# Ensure link_args are properly quoted
Expand Down Expand Up @@ -2289,7 +2281,7 @@ def test_guessed_linker_dependencies(self):
testdirbase = os.path.join(self.unit_test_dir, '29 guessed linker dependencies')
testdirlib = os.path.join(testdirbase, 'lib')
extra_args = None
env = Environment(testdirlib, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdirlib, self.builddir, self.prefix)
if env.detect_c_compiler(False).get_id() != 'msvc':
# static libraries are not linkable with -l with msvc because meson installs them
# as .a files which unix_args_to_native will not know as it expects libraries to use
Expand Down Expand Up @@ -2738,7 +2730,7 @@ def test_objc_cpp_detection(self):
'''
Test that when we can't detect objc or objcpp, we fail gracefully.
'''
env = Environment('', self.builddir, get_fake_options(self.prefix))
env = get_fake_env('', self.builddir, self.prefix)
try:
env.detect_objc_compiler(False)
env.detect_objcpp_compiler(False)
Expand Down Expand Up @@ -2875,7 +2867,7 @@ def test_ignore_libs(self):
ExternalLibraryHolder from build files.
'''
testdir = os.path.join(self.platform_test_dir, '1 basic')
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(False)
if cc.id != 'msvc':
raise unittest.SkipTest('Not using MSVC')
Expand All @@ -2888,7 +2880,7 @@ def test_rc_depends_files(self):
testdir = os.path.join(self.platform_test_dir, '5 resources')

# resource compiler depfile generation is not yet implemented for msvc
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
depfile_works = env.detect_c_compiler(False).get_id() != 'msvc'

self.init(testdir)
Expand Down Expand Up @@ -2977,7 +2969,7 @@ def test_pkgconfig_gen(self):
'''
testdir = os.path.join(self.common_test_dir, '48 pkgconfig-gen')
self.init(testdir)
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
kwargs = {'required': True, 'silent': True}
os.environ['PKG_CONFIG_LIBDIR'] = self.privatedir
foo_dep = PkgConfigDependency('libfoo', env, kwargs)
Expand Down Expand Up @@ -3233,7 +3225,7 @@ def test_compiler_c_stds(self):
an ordinary test because it requires passing options to meson.
'''
testdir = os.path.join(self.common_test_dir, '1 trivial')
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(False)
self._test_stds_impl(testdir, cc, 'c')

Expand All @@ -3243,7 +3235,7 @@ def test_compiler_cpp_stds(self):
be an ordinary test because it requires passing options to meson.
'''
testdir = os.path.join(self.common_test_dir, '2 cpp')
env = Environment(testdir, self.builddir, get_fake_options(self.prefix))
env = get_fake_env(testdir, self.builddir, self.prefix)
cpp = env.detect_cpp_compiler(False)
self._test_stds_impl(testdir, cpp, 'cpp')

Expand Down Expand Up @@ -3787,8 +3779,6 @@ def test_usage_external_library(self):
The system library is found with cc.find_library() and pkg-config deps.
'''
if not is_osx():
raise unittest.SkipTest('workflow currently only works on macOS')
oldprefix = self.prefix
# Install external library so we can find it
testdir = os.path.join(self.unit_test_dir, '39 external, internal library rpath', 'external library')
Expand All @@ -3811,6 +3801,9 @@ def test_usage_external_library(self):
self.build()
# test uninstalled
self.run_tests()
if not is_osx():
# Rest of the workflow only works on macOS
return
# test running after installation
self.install(use_destdir=False)
prog = os.path.join(self.installdir, 'bin', 'prog')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
project('built library', 'c')

cc = meson.get_compiler('c')

# bar_in_system has undefined symbols, but still must be found
bar_system_dep = cc.find_library('bar_in_system')

foo_system_dep = cc.find_library('foo_in_system')

faa_pkg_dep = dependency('faa_pkg')

l = shared_library('bar_built', 'bar.c',
install: true,
dependencies : [foo_system_dep, faa_pkg_dep])

e = executable('prog', 'prog.c', link_with: l, install: true)
test('testprog', e)
if host_machine.system() == 'darwin'
e = executable('prog', 'prog.c', link_with: l, install: true)
test('testprog', e)
endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
int some_undefined_func (void);

int bar_system_value (void)
{
return some_undefined_func ();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
project('system library', 'c')
project('system library', 'c', default_options : ['b_lundef=false'])

shared_library('foo_in_system', 'foo.c', install : true)
l = shared_library('faa_pkg', 'faa.c', install: true)

if host_machine.system() == 'darwin'
frameworks = ['-framework', 'CoreFoundation', '-framework', 'CoreMedia']
else
frameworks = []
endif

pkg = import('pkgconfig')
pkg.generate(name: 'faa_pkg',
libraries: [l, '-framework', 'CoreFoundation', '-framework', 'CoreMedia'],
libraries: [l] + frameworks,
description: 'FAA, a pkg-config test library')

shared_library('bar_in_system', 'bar.c', install : true)

0 comments on commit 14f8deb

Please sign in to comment.