diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 40776a9a9..b43977ea1 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -626,7 +626,7 @@ int dummy;
                              self.environment.get_import_lib_dir(),
                              # It has no aliases, should not be stripped, and
                              # doesn't have an install_rpath
-                             [], False, '']
+                             {}, False, '']
                         d.targets.append(i)
                     outdir = self.environment.get_shared_lib_dir()
                 elif isinstance(t, build.StaticLibrary):
@@ -641,16 +641,16 @@ int dummy;
                         # Install the debug symbols file in the same place as
                         # the target itself. It has no aliases, should not be
                         # stripped, and doesn't have an install_rpath
-                        i = [self.get_target_debug_filename(t), outdir, [], False, '']
+                        i = [self.get_target_debug_filename(t), outdir, {}, False, '']
                         d.targets.append(i)
                 if isinstance(t, build.BuildTarget):
-                    i = [self.get_target_filename(t), outdir, t.get_aliaslist(),\
-                        should_strip, t.install_rpath]
+                    i = [self.get_target_filename(t), outdir, t.get_aliases(),
+                         should_strip, t.install_rpath]
                     d.targets.append(i)
                 elif isinstance(t, build.CustomTarget):
                     for output in t.get_outputs():
                         f = os.path.join(self.get_target_dir(t), output)
-                        d.targets.append([f, outdir, [], False, None])
+                        d.targets.append([f, outdir, {}, False, None])
 
     def generate_custom_install_script(self, d):
         d.install_scripts = self.build.install_scripts
@@ -2087,22 +2087,15 @@ rule FORTRAN_DEP_HACK
 
     def generate_shlib_aliases(self, target, outdir):
         basename = target.get_filename()
-        aliases = target.get_aliaslist()
-        for i, alias in enumerate(aliases):
+        aliases = target.get_aliases()
+        for alias, to in aliases.items():
             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(pointed_to_filename, aliasfile)
+                os.symlink(to, 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 6e3325d75..c7d41259d 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -798,8 +798,8 @@ class BuildTarget():
         else:
             self.extra_args[language] = args
 
-    def get_aliaslist(self):
-        return []
+    def get_aliases(self):
+        return {}
 
     def get_clike_dynamic_linker(self):
         '''
@@ -1038,7 +1038,7 @@ class SharedLibrary(BuildTarget):
         First we determine the filename template (self.filename_tpl), then we
         set the output filename (self.filename).
 
-        The template is needed while creating aliases (self.get_aliaslist),
+        The template is needed while creating aliases (self.get_aliases),
         which are needed while generating .so shared libraries for Linux.
 
         Besides this, there's also the import library name, which is only used
@@ -1184,25 +1184,30 @@ class SharedLibrary(BuildTarget):
     def get_all_link_deps(self):
         return [self] + self.get_transitive_link_deps()
 
-    def get_aliaslist(self):
+    def get_aliases(self):
         """
         If the versioned library name is libfoo.so.0.100.0, aliases are:
-        * libfoo.so.0 (soversion)
-        * libfoo.so (unversioned; for linking)
+        * libfoo.so.0 (soversion) -> libfoo.so.0.100.0
+        * libfoo.so (unversioned; for linking) -> libfoo.so.0
         """
+        aliases = {}
         # Aliases are only useful with .so libraries. Also if the .so library
         # ends with .so (no versioning), we don't need aliases.
         if self.suffix != 'so' or self.filename.endswith('.so'):
-            return []
-        # Unversioned alias: libfoo.so
-        aliases = [self.basic_filename_tpl.format(self)]
-        # If ltversion != soversion we create an soversion alias: libfoo.so.X
+            return {}
+        # If ltversion != soversion we create an soversion alias:
+        # libfoo.so.0 -> libfoo.so.0.100.0
         if self.ltversion and self.ltversion != self.soversion:
             if not self.soversion:
                 # This is done in self.process_kwargs()
                 raise AssertionError('BUG: If library version is defined, soversion must have been defined')
             alias_tpl = self.filename_tpl.replace('ltversion', 'soversion')
-            aliases.append(alias_tpl.format(self))
+            ltversion_filename = alias_tpl.format(self)
+            aliases[ltversion_filename] = self.filename
+        else:
+            ltversion_filename = self.filename
+        # Unversioned alias: libfoo.so -> libfoo.so.0
+        aliases[self.basic_filename_tpl.format(self)] = ltversion_filename
         return aliases
 
     def type_suffix(self):
diff --git a/mesonbuild/modules/rpm.py b/mesonbuild/modules/rpm.py
index e3c45c0a0..ece16102d 100644
--- a/mesonbuild/modules/rpm.py
+++ b/mesonbuild/modules/rpm.py
@@ -55,7 +55,7 @@ class RPMModule:
                 files.add('%%{_bindir}/%s' % target.get_filename())
             elif isinstance(target, build.SharedLibrary) and target.need_install:
                 files.add('%%{_libdir}/%s' % target.get_filename())
-                for alias in target.get_aliaslist():
+                for alias in target.get_aliases():
                     if alias.endswith('.so'):
                         files_devel.add('%%{_libdir}/%s' % alias)
                     else:
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index 11dd32094..c749b4fae 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -222,14 +222,14 @@ def install_targets(d):
         else:
             raise RuntimeError('Unknown file type for {!r}'.format(fname))
         printed_symlink_error = False
-        for alias in aliases:
+        for alias, to in aliases.items():
             try:
                 symlinkfilename = os.path.join(outdir, alias)
                 try:
                     os.unlink(symlinkfilename)
                 except FileNotFoundError:
                     pass
-                os.symlink(os.path.split(fname)[-1], symlinkfilename)
+                os.symlink(to, symlinkfilename)
                 append_to_log(symlinkfilename)
             except (NotImplementedError, OSError):
                 if not printed_symlink_error:
diff --git a/run_unittests.py b/run_unittests.py
index d11c3f3bc..3d5a237ea 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -57,6 +57,9 @@ class LinuxlikeTests(unittest.TestCase):
         src_root = os.path.dirname(__file__)
         src_root = os.path.join(os.getcwd(), src_root)
         self.builddir = tempfile.mkdtemp()
+        self.prefix = '/usr'
+        self.libdir = os.path.join(self.prefix, 'lib')
+        self.installdir = os.path.join(self.builddir, 'install')
         self.meson_command = [sys.executable, os.path.join(src_root, 'meson.py')]
         self.mconf_command = [sys.executable, os.path.join(src_root, 'mesonconf.py')]
         self.mintro_command = [sys.executable, os.path.join(src_root, 'mesonintrospect.py')]
@@ -77,11 +80,18 @@ class LinuxlikeTests(unittest.TestCase):
         self.output += subprocess.check_output(command, env=os.environ.copy())
 
     def init(self, srcdir):
-        self._run(self.meson_command + [srcdir, self.builddir])
+        args = [srcdir, self.builddir,
+                '--prefix', self.prefix,
+                '--libdir', self.libdir]
+        self._run(self.meson_command + args)
 
     def build(self):
         self._run(self.ninja_command)
 
+    def install(self):
+        os.environ['DESTDIR'] = self.installdir
+        self._run(self.ninja_command + ['install'])
+
     def run_target(self, target):
         self.output += subprocess.check_output(self.ninja_command + [target])
 
@@ -236,8 +246,8 @@ class LinuxlikeTests(unittest.TestCase):
         intro = self.introspect('--targets')
         if intro[0]['type'] == 'executable':
             intro = intro[::-1]
-        self.assertEqual(intro[0]['install_filename'], '/usr/local/libtest/libstat.a')
-        self.assertEqual(intro[1]['install_filename'], '/usr/local/bin/prog')
+        self.assertEqual(intro[0]['install_filename'], '/usr/lib/libstat.a')
+        self.assertEqual(intro[1]['install_filename'], '/usr/bin/prog')
 
     def test_run_target_files_path(self):
         '''
@@ -282,47 +292,55 @@ class LinuxlikeTests(unittest.TestCase):
                 return line.split('[')[1].split(']')[0]
         raise RuntimeError('Readelf gave no SONAME.')
 
-    def test_soname(self):
+    def _test_soname_impl(self, libpath, install):
         testdir = os.path.join(self.unit_test_dir, '1 soname')
         self.init(testdir)
         self.build()
+        if install:
+            self.install()
 
         # File without aliases set.
-        nover = os.path.join(self.builddir, 'libnover.so')
+        nover = os.path.join(libpath, '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')
+        verset = os.path.join(libpath, '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')
+        soverset = os.path.join(libpath, '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')
+        settosame = os.path.join(libpath, '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')
+        bothset = os.path.join(libpath, '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)
 
+    def test_soname(self):
+        self._test_soname_impl(self.builddir, False)
+
+    def test_installed_soname(self):
+        self._test_soname_impl(self.installdir + self.libdir, True)
+
     def test_compiler_check_flags_order(self):
         '''
         Test that compiler check flags override all other flags. This can't be
diff --git a/test cases/unit/1 soname/meson.build b/test cases/unit/1 soname/meson.build
index d956afed9..950dadc5d 100644
--- a/test cases/unit/1 soname/meson.build	
+++ b/test cases/unit/1 soname/meson.build	
@@ -1,18 +1,22 @@
 project('vertest', 'c')
 
-shared_library('nover', 'versioned.c')
+shared_library('nover', 'versioned.c',
+ install : true)
 
 shared_library('verset', 'versioned.c',
+ install : true,
  version : '4.5.6')
 
 shared_library('soverset', 'versioned.c',
+ install : true,
  soversion : '1.2.3')
 
 shared_library('bothset', 'versioned.c',
+ install : true,
  soversion : '1.2.3',
  version : '4.5.6')
 
 shared_library('settosame', 'versioned.c',
+  install : true,
   soversion : '7.8.9',
   version : '7.8.9')
-