aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2018-06-05 17:37:02 +0530
committerNirbheek Chauhan <nirbheek.chauhan@gmail.com>2018-06-18 06:33:23 +0000
commit5467eed186c0576704b3d6de2e8d2d8a8ca6ad35 (patch)
tree7a34518aa7a5948647d7e8c59b771e99902f7dfe
parent6e2ee246197a8dd12e8f147975b79599dc881360 (diff)
downloadmeson-5467eed186c0576704b3d6de2e8d2d8a8ca6ad35.zip
meson-5467eed186c0576704b3d6de2e8d2d8a8ca6ad35.tar.gz
meson-5467eed186c0576704b3d6de2e8d2d8a8ca6ad35.tar.bz2
Test that binaries that use external libraries work
When we link to an external library either with find_library() without any dirs:, or with dependency(), we should be able to run uninstalled out of the box without having to set any environment variables or other shenanigans. This is especially important on macOS because only the system frameworks directory is in the default runtime path, and all other frameworks and libraries need to be found with RPATH or absolute path to the dylib.
-rw-r--r--.travis.yml2
-rwxr-xr-xrun_unittests.py65
-rw-r--r--test cases/unit/33 external, internal library rpath/built library/bar.c7
-rw-r--r--test cases/unit/33 external, internal library rpath/built library/meson.build11
-rw-r--r--test cases/unit/33 external, internal library rpath/built library/meson_options.txt1
-rw-r--r--test cases/unit/33 external, internal library rpath/built library/prog.c7
-rw-r--r--test cases/unit/33 external, internal library rpath/external library/faa.c4
-rw-r--r--test cases/unit/33 external, internal library rpath/external library/foo.c4
-rw-r--r--test cases/unit/33 external, internal library rpath/external library/meson.build9
9 files changed, 96 insertions, 14 deletions
diff --git a/.travis.yml b/.travis.yml
index 62385d6..6f31f99 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,7 +42,7 @@ before_install:
- python ./skip_ci.py --base-branch-env=TRAVIS_BRANCH --is-pull-env=TRAVIS_PULL_REQUEST
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew uninstall python mercurial; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python@2 python@3 mercurial qt; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python@2 python@3 mercurial qt pkg-config; fi
# Use a Ninja with QuLogic's patch: https://github.com/ninja-build/ninja/issues/1219
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir -p $HOME/tools; curl -L http://nirbheek.in/files/binaries/ninja/macos/ninja -o $HOME/tools/ninja; chmod +x $HOME/tools/ninja; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull jpakkane/mesonci:bionic; fi
diff --git a/run_unittests.py b/run_unittests.py
index 7c68904..c4d9547 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -74,6 +74,19 @@ def get_soname(fname):
def get_rpath(fname):
return get_dynamic_section_entry(fname, r'(?:rpath|runpath)')
+def skipIfNoPkgconfig(f):
+ '''
+ Skip this test if no pkg-config is found, unless we're on Travis CI
+ This allows users to run our test suite without having pkg-config installed
+ on, f.ex., macOS, while ensuring that our Travis CI does not silently skip
+ the test because of misconfiguration.
+ '''
+ def wrapped(*args, **kwargs):
+ if 'TRAVIS' not in os.environ and shutil.which('pkg-config') is None:
+ raise unittest.SkipTest('pkg-config not found')
+ return f(*args, **kwargs)
+ return wrapped
+
class InternalTests(unittest.TestCase):
@@ -484,7 +497,7 @@ class BasePlatformTests(unittest.TestCase):
src_root = os.path.join(os.getcwd(), src_root)
self.src_root = src_root
self.prefix = '/usr'
- self.libdir = os.path.join(self.prefix, 'lib')
+ self.libdir = 'lib'
# Get the backend
# FIXME: Extract this from argv?
self.backend = getattr(Backend, os.environ.get('MESON_UNIT_TEST_BACKEND', 'ninja'))
@@ -1656,6 +1669,7 @@ int main(int argc, char **argv) {
if os.path.splitext(fname)[1] not in ['.c', '.h']:
os.unlink(fname)
+ @skipIfNoPkgconfig
def test_pkgconfig_static(self):
'''
Test that the we prefer static libraries when `static: true` is
@@ -1666,8 +1680,6 @@ int main(int argc, char **argv) {
since system libraries -lm will never be found statically.
https://github.com/mesonbuild/meson/issues/2785
'''
- if not shutil.which('pkg-config'):
- raise unittest.SkipTest('pkg-config not found')
(cc, stlinker, objext, shext) = self.detect_prebuild_env()
testdir = os.path.join(self.unit_test_dir, '17 pkgconfig static')
source = os.path.join(testdir, 'foo.c')
@@ -1699,9 +1711,8 @@ int main(int argc, char **argv) {
if os.path.splitext(fname)[1] not in ['.c', '.h', '.in']:
os.unlink(fname)
+ @skipIfNoPkgconfig
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'
@@ -2264,9 +2275,8 @@ class FailureTests(BasePlatformTests):
out = self.init(self.srcdir, extra_args=extra_args, inprocess=True)
self.assertRegex(out, match)
+ @skipIfNoPkgconfig
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"),
@@ -2660,13 +2670,12 @@ class LinuxlikeTests(BasePlatformTests):
self.assertIn(" -Werror ", vala_command)
self.assertIn(" -Werror ", c_command)
+ @skipIfNoPkgconfig
def test_qt5dependency_pkgconfig_detection(self):
'''
Test that qt4 and qt5 detection with pkgconfig works.
'''
# Verify Qt4 or Qt5 can be found with pkg-config
- if not shutil.which('pkg-config'):
- raise unittest.SkipTest('pkg-config not found')
qt4 = subprocess.call(['pkg-config', '--exists', 'QtCore'])
qt5 = subprocess.call(['pkg-config', '--exists', 'Qt5Core'])
if qt4 != 0 or qt5 != 0:
@@ -3206,7 +3215,7 @@ endian = 'little'
self.build()
mesonbuild.modules.gnome.native_glib_version = None
- @unittest.skipIf(shutil.which('pkg-config') is None, 'Pkg-config not found.')
+ @skipIfNoPkgconfig
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')
@@ -3242,7 +3251,7 @@ endian = 'little'
self.assertTrue(os.path.isfile(test_exe))
subprocess.check_call(test_exe, env=myenv)
- @unittest.skipIf(shutil.which('pkg-config') is None, 'Pkg-config not found.')
+ @skipIfNoPkgconfig
def test_pkgconfig_internal_libraries(self):
'''
'''
@@ -3263,7 +3272,7 @@ endian = 'little'
self.init(os.path.join(testdirbase, 'app'))
self.build()
- @unittest.skipIf(shutil.which('pkg-config') is None, 'Pkg-config not found.')
+ @skipIfNoPkgconfig
def test_pkgconfig_formatting(self):
testdir = os.path.join(self.unit_test_dir, '31 pkgconfig format')
self.init(testdir)
@@ -3271,7 +3280,7 @@ endian = 'little'
myenv['PKG_CONFIG_PATH'] = self.privatedir
stdo = subprocess.check_output(['pkg-config', '--libs-only-l', 'libsomething'], env=myenv)
deps = [b'-lgobject-2.0', b'-lgio-2.0', b'-lglib-2.0', b'-lsomething']
- if is_windows() or is_cygwin():
+ if is_windows() or is_cygwin() or is_osx():
# On Windows, libintl is a separate library
deps.append(b'-lintl')
self.assertEqual(set(deps), set(stdo.split()))
@@ -3323,6 +3332,36 @@ endian = 'little'
self.build()
self.run_tests()
+ @skipIfNoPkgconfig
+ def test_uninstalled_usage_external_library(self):
+ '''
+ Test that uninstalled usage of an external library (from the system or
+ PkgConfigDependency) works. On Linux/BSD/macOS it tests if RPATHs are
+ set correctly.
+
+ TODO: On Windows, this can test whether PATH is set properly
+
+ The system library is found with cc.find_library() and pkg-config deps.
+ '''
+ oldprefix = self.prefix
+ # Install external library so we can find it
+ testdir = os.path.join(self.unit_test_dir, '33 external, internal library rpath', 'external library')
+ installdir = self.installdir
+ self.prefix = installdir
+ self.init(testdir)
+ self.build()
+ self.install(use_destdir=False)
+ self.prefix = oldprefix
+ # New builddir for the consumer
+ self.new_builddir()
+ os.environ['LIBRARY_PATH'] = os.path.join(installdir, self.libdir)
+ os.environ['PKG_CONFIG_PATH'] = os.path.join(installdir, self.libdir, 'pkgconfig')
+ testdir = os.path.join(self.unit_test_dir, '33 external, internal library rpath', 'built library')
+ self.init(testdir)
+ self.build()
+ self.run_tests()
+
+
class LinuxArmCrossCompileTests(BasePlatformTests):
'''
Tests that verify cross-compilation to Linux/ARM
diff --git a/test cases/unit/33 external, internal library rpath/built library/bar.c b/test cases/unit/33 external, internal library rpath/built library/bar.c
new file mode 100644
index 0000000..4f5662e
--- /dev/null
+++ b/test cases/unit/33 external, internal library rpath/built library/bar.c
@@ -0,0 +1,7 @@
+int foo_system_value (void);
+int faa_system_value (void);
+
+int bar_built_value (int in)
+{
+ return faa_system_value() + foo_system_value() + in;
+}
diff --git a/test cases/unit/33 external, internal library rpath/built library/meson.build b/test cases/unit/33 external, internal library rpath/built library/meson.build
new file mode 100644
index 0000000..cb58f09
--- /dev/null
+++ b/test cases/unit/33 external, internal library rpath/built library/meson.build
@@ -0,0 +1,11 @@
+project('built library', 'c')
+
+cc = meson.get_compiler('c')
+foo_system_dep = cc.find_library('foo_in_system')
+faa_pkg_dep = dependency('faa_pkg')
+
+l = shared_library('bar_built', 'bar.c',
+ dependencies : [foo_system_dep, faa_pkg_dep])
+
+e = executable('prog', 'prog.c', link_with: l)
+test('testprog', e)
diff --git a/test cases/unit/33 external, internal library rpath/built library/meson_options.txt b/test cases/unit/33 external, internal library rpath/built library/meson_options.txt
new file mode 100644
index 0000000..aa1d2ec
--- /dev/null
+++ b/test cases/unit/33 external, internal library rpath/built library/meson_options.txt
@@ -0,0 +1 @@
+option('foo_system_path', type: 'string', value: '')
diff --git a/test cases/unit/33 external, internal library rpath/built library/prog.c b/test cases/unit/33 external, internal library rpath/built library/prog.c
new file mode 100644
index 0000000..e3d4cf6
--- /dev/null
+++ b/test cases/unit/33 external, internal library rpath/built library/prog.c
@@ -0,0 +1,7 @@
+int bar_built_value (int in);
+
+int main (int argc, char *argv[])
+{
+ // this will evaluate to 0
+ return bar_built_value(10) - (42 + 1969 + 10);
+}
diff --git a/test cases/unit/33 external, internal library rpath/external library/faa.c b/test cases/unit/33 external, internal library rpath/external library/faa.c
new file mode 100644
index 0000000..4733575
--- /dev/null
+++ b/test cases/unit/33 external, internal library rpath/external library/faa.c
@@ -0,0 +1,4 @@
+int faa_system_value (void)
+{
+ return 1969;
+}
diff --git a/test cases/unit/33 external, internal library rpath/external library/foo.c b/test cases/unit/33 external, internal library rpath/external library/foo.c
new file mode 100644
index 0000000..a34e4a8
--- /dev/null
+++ b/test cases/unit/33 external, internal library rpath/external library/foo.c
@@ -0,0 +1,4 @@
+int foo_system_value (void)
+{
+ return 42;
+}
diff --git a/test cases/unit/33 external, internal library rpath/external library/meson.build b/test cases/unit/33 external, internal library rpath/external library/meson.build
new file mode 100644
index 0000000..0e9f443
--- /dev/null
+++ b/test cases/unit/33 external, internal library rpath/external library/meson.build
@@ -0,0 +1,9 @@
+project('system library', 'c')
+
+shared_library('foo_in_system', 'foo.c', install : true)
+l = shared_library('faa_pkg', 'faa.c', install: true)
+
+pkg = import('pkgconfig')
+pkg.generate(name: 'faa_pkg',
+ libraries: l,
+ description: 'FAA, a pkg-config test library')