aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/ninjabackend.py11
-rw-r--r--mesonbuild/build.py6
-rw-r--r--mesonbuild/mesonmain.py4
-rw-r--r--mesonbuild/modules/gnome.py29
-rw-r--r--mesonbuild/modules/i18n.py12
-rw-r--r--mesonbuild/modules/pkgconfig.py1
-rw-r--r--mesonbuild/wrap/wrap.py2
-rwxr-xr-xmesontest.py13
-rwxr-xr-xrun_project_tests.py9
-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
13 files changed, 160 insertions, 25 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/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 1d4863c..71d42e3 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -115,7 +115,9 @@ class MesonApp():
msg = '''Trying to run Meson on a build directory that has already been configured.
If you want to build it, just run your build command (e.g. ninja) inside the
build directory. Meson will autodetect any changes in your setup and regenerate
-itself as required.'''
+itself as required.
+
+If you want to change option values, use the mesonconf tool instead.'''
raise RuntimeError(msg)
else:
if handshake:
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 7c4fb1d..38b3319 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -37,6 +37,13 @@ native_glib_version = None
girwarning_printed = False
gresource_warning_printed = False
+def find_program(program_name, target_name):
+ program = dependencies.ExternalProgram(program_name)
+ if not program.found():
+ raise MesonException('%s can\'t be generated as %s could not be found' % (
+ target_name, program_name))
+ return program
+
class GnomeModule:
@staticmethod
@@ -308,6 +315,8 @@ can not be used with the current version of glib-compiled-resources, due to
raise MesonException('Gir takes one argument')
if kwargs.get('install_dir'):
raise MesonException('install_dir is not supported with generate_gir(), see "install_dir_gir" and "install_dir_typelib"')
+ giscanner = find_program('g-ir-scanner', 'Gir')
+ gicompiler = find_program('g-ir-compiler', 'Gir')
girtarget = args[0]
while hasattr(girtarget, 'held_object'):
girtarget = girtarget.held_object
@@ -329,7 +338,7 @@ can not be used with the current version of glib-compiled-resources, due to
depends = [girtarget]
gir_inc_dirs = []
- scan_command = ['g-ir-scanner', '@INPUT@']
+ scan_command = giscanner.get_command() + ['@INPUT@']
scan_command += pkgargs
scan_command += ['--no-libtool', '--namespace='+ns, '--nsversion=' + nsversion, '--warn-all',
'--output', '@OUTPUT@']
@@ -484,7 +493,7 @@ can not be used with the current version of glib-compiled-resources, due to
scan_target = GirTarget(girfile, state.subdir, scankwargs)
typelib_output = '%s-%s.typelib' % (ns, nsversion)
- typelib_cmd = ['g-ir-compiler', scan_target, '--output', '@OUTPUT@']
+ typelib_cmd = gicompiler.get_command() + [scan_target, '--output', '@OUTPUT@']
typelib_cmd += self._get_include_args(state, gir_inc_dirs,
prefix='--includedir=')
for incdir in typelib_includes:
@@ -506,7 +515,9 @@ can not be used with the current version of glib-compiled-resources, due to
raise MesonException('Compile_schemas does not take positional arguments.')
srcdir = os.path.join(state.build_to_src, state.subdir)
outdir = state.subdir
- cmd = ['glib-compile-schemas', '--targetdir', outdir, srcdir]
+
+ cmd = find_program('glib-compile-schemas', 'gsettings-compile').get_command()
+ cmd += ['--targetdir', outdir, srcdir]
kwargs['command'] = cmd
kwargs['input'] = []
kwargs['output'] = 'gschemas.compiled'
@@ -684,7 +695,8 @@ can not be used with the current version of glib-compiled-resources, due to
raise MesonException('Gdbus_codegen takes two arguments, name and xml file.')
namebase = args[0]
xml_file = args[1]
- cmd = ['gdbus-codegen']
+ target_name = namebase + '-gdbus'
+ cmd = find_program('gdbus-codegen', target_name).get_command()
if 'interface_prefix' in kwargs:
cmd += ['--interface-prefix', kwargs.pop('interface_prefix')]
if 'namespace' in kwargs:
@@ -695,7 +707,7 @@ can not be used with the current version of glib-compiled-resources, due to
'output' : outputs,
'command' : cmd
}
- return build.CustomTarget(namebase + '-gdbus', state.subdir, custom_kwargs)
+ return build.CustomTarget(target_name, state.subdir, custom_kwargs)
def mkenums(self, state, args, kwargs):
if len(args) != 1:
@@ -741,7 +753,7 @@ can not be used with the current version of glib-compiled-resources, due to
elif arg not in known_custom_target_kwargs:
raise MesonException(
'Mkenums does not take a %s keyword argument.' % (arg, ))
- cmd = ['glib-mkenums'] + cmd
+ cmd = find_program('glib-mkenums', 'mkenums').get_command() + cmd
custom_kwargs = {}
for arg in known_custom_target_kwargs:
if arg in kwargs:
@@ -822,7 +834,7 @@ can not be used with the current version of glib-compiled-resources, due to
raise MesonException(
'Sources keyword argument must be a string or array.')
- cmd = ['glib-genmarshal']
+ cmd = find_program('glib-genmarshal', output + '_genmarshal').get_command()
known_kwargs = ['internal', 'nostdinc', 'skip_source', 'stdinc',
'valist_marshallers']
known_custom_target_kwargs = ['build_always', 'depends',
@@ -949,7 +961,8 @@ can not be used with the current version of glib-compiled-resources, due to
build_dir = os.path.join(state.environment.get_build_dir(), state.subdir)
source_dir = os.path.join(state.environment.get_source_dir(), state.subdir)
pkg_cmd, vapi_depends, vapi_packages, vapi_includes = self._extract_vapi_packages(state, kwargs)
- cmd = ['vapigen', '--quiet', '--library=' + library, '--directory=' + build_dir]
+ cmd = find_program('vapigen', 'Vaapi').get_command()
+ cmd += ['--quiet', '--library=' + library, '--directory=' + build_dir]
cmd += self._vapi_args_to_command('--vapidir=', 'vapi_dirs', kwargs)
cmd += self._vapi_args_to_command('--metadatadir=', 'metadata_dirs', kwargs)
cmd += self._vapi_args_to_command('--girdir=', 'gir_dirs', kwargs)
diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py
index 1ddb2fc..bb1b2f8 100644
--- a/mesonbuild/modules/i18n.py
+++ b/mesonbuild/modules/i18n.py
@@ -12,16 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from os import path
from .. import coredata, mesonlib, build
import sys
class I18nModule:
+ @staticmethod
+ def _read_linguas(state):
+ linguas = path.join(state.environment.get_source_dir(), state.subdir, 'LINGUAS')
+ try:
+ with open(linguas) as f:
+ return [line.strip() for line in f if not line.strip().startswith('#')]
+ except (FileNotFoundError, PermissionError):
+ return []
+
def gettext(self, state, args, kwargs):
if len(args) != 1:
raise coredata.MesonException('Gettext requires one positional argument (package name).')
packagename = args[0]
- languages = mesonlib.stringlistify(kwargs.get('languages', []))
+ languages = mesonlib.stringlistify(kwargs.get('languages', self._read_linguas(state)))
if len(languages) == 0:
raise coredata.MesonException('List of languages empty.')
datadirs = mesonlib.stringlistify(kwargs.get('data_dirs', []))
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 9f50b0e..73b29ae 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -49,6 +49,7 @@ class PkgConfigModule:
# '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('\n')
ofile.write('Name: %s\n' % name)
if len(description) > 0:
ofile.write('Description: %s\n' % description)
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index 19ed39a..37d6df7 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -153,7 +153,7 @@ class Resolver:
if revno.lower() != 'head':
subprocess.check_call(['git', 'checkout', revno],
cwd=checkoutdir)
- push_url = p.get('push-url')
+ push_url = p.values.get('push-url')
if push_url:
subprocess.check_call(['git', 'remote', 'set-url',
'--push', 'origin', push_url],
diff --git a/mesontest.py b/mesontest.py
index 293678b..849e32d 100755
--- a/mesontest.py
+++ b/mesontest.py
@@ -150,7 +150,6 @@ class TestHarness:
self.datafile = os.path.join(options.wd, 'meson-private/meson_benchmark_setup.dat')
else:
self.datafile = os.path.join(options.wd, 'meson-private/meson_test_setup.dat')
- print(self.datafile)
def run_single_test(self, wrap, test):
if test.fname[0].endswith('.jar'):
@@ -399,12 +398,12 @@ class TestHarness:
else:
res = self.run_single_test(wrap, t)
if (res.returncode == 0 and res.should_fail) or \
- (res.returncode != 0 and not res.should_fail) and \
- not self.options.verbose:
- print('Test failed:\n\n-- stdout --\n')
- print(res.stdo)
- print('\n-- stderr --\n')
- print(res.stde)
+ (res.returncode != 0 and not res.should_fail):
+ if not self.options.verbose:
+ print('Test failed:\n\n-- stdout --\n')
+ print(res.stdo)
+ print('\n-- stderr --\n')
+ print(res.stde)
return 1
return 0
diff --git a/run_project_tests.py b/run_project_tests.py
index dcc6006..6f4d0a3 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -380,7 +380,14 @@ def run_tests(extra_args):
build_time = 0
test_time = 0
- executor = conc.ProcessPoolExecutor(max_workers=multiprocessing.cpu_count())
+ try:
+ # This fails in some CI environments for unknown reasons.
+ num_workers = multiprocessing.cpu_count()
+ except Exception as e:
+ print('Could not determine number of CPUs due to the following reason:' + str(e))
+ print('Defaulting to using only one process')
+ num_workers = 1
+ executor = conc.ProcessPoolExecutor(max_workers=num_workers)
for name, test_cases, skipped in all_tests:
current_suite = ET.SubElement(junit_root, 'testsuite', {'name' : name, 'tests' : str(len(test_cases))})
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;
+}