aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/ninjabackend.py11
-rw-r--r--mesonbuild/build.py6
-rwxr-xr-xrun_unittests.py51
-rw-r--r--test cases/unit/1 soname/CMakeLists.txt26
-rw-r--r--test cases/unit/1 soname/meson.build18
-rw-r--r--test cases/unit/1 soname/versioned.c3
6 files changed, 109 insertions, 6 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 659a53d..bd65cbe 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2004,14 +2004,21 @@ rule FORTRAN_DEP_HACK
def generate_shlib_aliases(self, target, outdir):
basename = target.get_filename()
aliases = target.get_aliaslist()
- for alias in aliases:
+ for i, alias in enumerate(aliases):
aliasfile = os.path.join(self.environment.get_build_dir(), outdir, alias)
try:
os.remove(aliasfile)
except Exception:
pass
+ # If both soversion and version are set and to different values,
+ # the .so symlink must point to the soversion symlink rather than the
+ # original file.
+ if i == 0 and len(aliases) > 1:
+ pointed_to_filename = aliases[1]
+ else:
+ pointed_to_filename = basename
try:
- os.symlink(basename, aliasfile)
+ os.symlink(pointed_to_filename, aliasfile)
except NotImplementedError:
mlog.debug("Library versioning disabled because symlinks are not supported.")
except OSError:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 39e215f..462a55b 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1069,12 +1069,10 @@ class SharedLibrary(BuildTarget):
self.soversion = str(self.soversion)
if not isinstance(self.soversion, str):
raise InvalidArguments('Shared library soversion is not a string or integer.')
- try:
- int(self.soversion)
- except ValueError:
- raise InvalidArguments('Shared library soversion must be a valid integer')
elif self.ltversion:
# library version is defined, get the soversion from that
+ # We replicate what Autotools does here and take the first
+ # number of the version by default.
self.soversion = self.ltversion.split('.')[0]
# Visual Studio module-definitions file
if 'vs_module_defs' in kwargs:
diff --git a/run_unittests.py b/run_unittests.py
index 39e93c9..8b1f13f 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -17,6 +17,7 @@ import unittest, os, sys, shutil, time
import subprocess
import re, json
import tempfile
+from glob import glob
import mesonbuild.environment
from mesonbuild.environment import detect_ninja
from mesonbuild.dependencies import PkgConfigDependency, Qt5Dependency
@@ -52,6 +53,7 @@ class LinuxlikeTests(unittest.TestCase):
def setUp(self):
super().setUp()
src_root = os.path.dirname(__file__)
+ src_root = os.path.join(os.getcwd(), src_root)
self.builddir = tempfile.mkdtemp()
self.meson_command = [sys.executable, os.path.join(src_root, 'meson.py')]
self.mconf_command = [sys.executable, os.path.join(src_root, 'mesonconf.py')]
@@ -60,6 +62,7 @@ class LinuxlikeTests(unittest.TestCase):
self.common_test_dir = os.path.join(src_root, 'test cases/common')
self.vala_test_dir = os.path.join(src_root, 'test cases/vala')
self.framework_test_dir = os.path.join(src_root, 'test cases/frameworks')
+ self.unit_test_dir = os.path.join(src_root, 'test cases/unit')
self.output = b''
self.orig_env = os.environ.copy()
@@ -211,5 +214,53 @@ class LinuxlikeTests(unittest.TestCase):
mesonlog = self.get_meson_log()
self.assertTrue(msg in mesonlog or msg2 in mesonlog)
+ def get_soname(self, fname):
+ output = subprocess.check_output(['readelf', '-a', fname])
+ for line in output.decode('utf-8', errors='ignore').split('\n'):
+ if 'SONAME' in line:
+ return line.split('[')[1].split(']')[0]
+ raise RuntimeError('Readelf gave no SONAME.')
+
+ def test_soname(self):
+ testdir = os.path.join(self.unit_test_dir, '1 soname')
+ self.init(testdir)
+ self.build()
+
+ # File without aliases set.
+ nover = os.path.join(self.builddir, 'libnover.so')
+ self.assertTrue(os.path.exists(nover))
+ self.assertFalse(os.path.islink(nover))
+ self.assertEqual(self.get_soname(nover), 'libnover.so')
+ self.assertEqual(len(glob(nover[:-3] + '*')), 1)
+
+ # File with version set
+ verset = os.path.join(self.builddir, 'libverset.so')
+ self.assertTrue(os.path.exists(verset + '.4.5.6'))
+ self.assertEqual(os.readlink(verset), 'libverset.so.4')
+ self.assertEqual(self.get_soname(verset), 'libverset.so.4')
+ self.assertEqual(len(glob(verset[:-3] + '*')), 3)
+
+ # File with soversion set
+ soverset = os.path.join(self.builddir, 'libsoverset.so')
+ self.assertTrue(os.path.exists(soverset + '.1.2.3'))
+ self.assertEqual(os.readlink(soverset), 'libsoverset.so.1.2.3')
+ self.assertEqual(self.get_soname(soverset), 'libsoverset.so.1.2.3')
+ self.assertEqual(len(glob(soverset[:-3] + '*')), 2)
+
+ # File with version and soversion set to same values
+ settosame = os.path.join(self.builddir, 'libsettosame.so')
+ self.assertTrue(os.path.exists(settosame + '.7.8.9'))
+ self.assertEqual(os.readlink(settosame), 'libsettosame.so.7.8.9')
+ self.assertEqual(self.get_soname(settosame), 'libsettosame.so.7.8.9')
+ self.assertEqual(len(glob(settosame[:-3] + '*')), 2)
+
+ # File with version and soversion set to different values
+ bothset = os.path.join(self.builddir, 'libbothset.so')
+ self.assertTrue(os.path.exists(bothset + '.1.2.3'))
+ self.assertEqual(os.readlink(bothset), 'libbothset.so.1.2.3')
+ self.assertEqual(os.readlink(bothset + '.1.2.3'), 'libbothset.so.4.5.6')
+ self.assertEqual(self.get_soname(bothset), 'libbothset.so.1.2.3')
+ self.assertEqual(len(glob(bothset[:-3] + '*')), 3)
+
if __name__ == '__main__':
unittest.main()
diff --git a/test cases/unit/1 soname/CMakeLists.txt b/test cases/unit/1 soname/CMakeLists.txt
new file mode 100644
index 0000000..c4f2e3e
--- /dev/null
+++ b/test cases/unit/1 soname/CMakeLists.txt
@@ -0,0 +1,26 @@
+# This is a CMake version of this test. It behaves slightly differently
+# so in case you ever need to debug this, here it is.
+#
+# The biggest difference is that if SOVERSION is not set, it
+# is set to VERSION. Autotools sets it to the first number
+# of VERSION. That is, for version number 1.2.3 CMake sets
+# soname to 1.2.3 but Autotools sets it to 1.
+
+project(vertest C)
+cmake_minimum_required(VERSION 3.5)
+
+add_library(nover SHARED versioned.c)
+
+add_library(verset SHARED versioned.c)
+set_target_properties(verset PROPERTIES VERSION 4.5.6)
+
+add_library(soverset SHARED versioned.c)
+set_target_properties(soverset PROPERTIES SOVERSION 1.2.3)
+
+add_library(bothset SHARED versioned.c)
+set_target_properties(bothset PROPERTIES SOVERSION 1.2.3)
+set_target_properties(bothset PROPERTIES VERSION 4.5.6)
+
+add_library(settosame SHARED versioned.c)
+set_target_properties(settosame PROPERTIES SOVERSION 7.8.9)
+set_target_properties(settosame PROPERTIES VERSION 7.8.9)
diff --git a/test cases/unit/1 soname/meson.build b/test cases/unit/1 soname/meson.build
new file mode 100644
index 0000000..d956afe
--- /dev/null
+++ b/test cases/unit/1 soname/meson.build
@@ -0,0 +1,18 @@
+project('vertest', 'c')
+
+shared_library('nover', 'versioned.c')
+
+shared_library('verset', 'versioned.c',
+ version : '4.5.6')
+
+shared_library('soverset', 'versioned.c',
+ soversion : '1.2.3')
+
+shared_library('bothset', 'versioned.c',
+ soversion : '1.2.3',
+ version : '4.5.6')
+
+shared_library('settosame', 'versioned.c',
+ soversion : '7.8.9',
+ version : '7.8.9')
+
diff --git a/test cases/unit/1 soname/versioned.c b/test cases/unit/1 soname/versioned.c
new file mode 100644
index 0000000..f48d2b0
--- /dev/null
+++ b/test cases/unit/1 soname/versioned.c
@@ -0,0 +1,3 @@
+int versioned_func() {
+ return 0;
+}