Repository: mesonbuild/meson

Issue:
Installation prefix is wrong when using --prefix on meson or DESDIR in ninja
It seems that both of them are adding the build machine architecture for installation. 

Instead of using /usr/lib or /usr/local/lib it's using usr/lib/x86_64-linux-gnu and usr/local/lib/x86_64-linux-gnu. 

This is because I'm compiling for ARM in a X86_64 machine. That's completely wrong. Even if the binary created and installed on that path is for ARM the path is wrong.

In my case:

/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot/usr/local/lib/x86_64-linux-gnu/libsg64_core.so

I will also override the values for the prefix and DESTDIR in the cross-file so it can be safely changed when cross-compile in opposition of a normal target build on x86_64 architecture. 

So something like this should work.

```ini
[binaries]
c = '/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/bin/arm-linux-gcc'
cpp = '/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/bin/arm-linux-g++'
ar = '/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/bin/arm-linux-ar'
strip = '/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/bin/arm-linux-strip'
pkgconfig = '/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/bin/pkg-config'

[properties]
root = '/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot'
DESTDIR = '/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot'
prefix= '/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot'
c_args = ['-DTARGET_MACHINE=VAL100',
					'--sysroot=/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot']
c_link_args = ['--sysroot=/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot']
cpp_args = ['--sysroot=/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot']
cpp_link_args = ['--sysroot=/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot']



[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv7hl'
endian = 'little'

[target_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv7hl'
endian = 'little'
```

I can call meson with prefix:

meson --prefix /opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot . build-val100/ --cross-file val100-cross.txt

or I can install with DESTDIR:

DESTDIR=/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot ninja install

But also if I use both. Both paths are added to the installation:

Installing src/libsg64_core.so to /opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot/opt/VAL100/buildroot/buildroot-2015.05/output/host/usr/arm-buildroot-linux-gnueabihf/sysroot/lib/x86_64-linux-gnu/libsg64_core.so

So they are not compatible I think...


Discussion:
meson --version
0.42.1

`DESTDIR` is just where to place the files, it should not include the `prefix` and its only used for packaging purposes.
I think this is largely a technicality; DESTDIR can also be the same as prefix, even if it may be nonsensical (the --prefix already would have been specified by the user).

I like to think of DESTDIR as simply providing more flexibility for those users who may want to have it. The official description appears to reinforce that notation, for example:

https://www.gnu.org/prep/standards/html_node/DESTDIR.html

"Finally, it can be useful with tools such as stow, where code is installed in one place but made to appear to be installed somewhere else using symbolic links or special mount operations."

E. g. a user to install into his $HOME directory, and/or for testing purposes.

If I understood gadLinux correctly so, then his issue appears to be an automatic conversion towards names such as x86_64-linux-gnu etc... ? I do not know how meson solves this but I think that GNU autoconfigure allowed separate --prefix targets for target library paths too.
My workaround in configure. destdir handles the cross part
```
meson --prefix=/usr --libdir=lib 
```
It is apparently the default value of libdir which is causing the problem.
#4636 might be relevant

Resolving patch:
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -299,6 +299,7 @@ def __init__(self, options):
         # Only to print a warning if it changes between Meson invocations.
         self.pkgconf_envvar = os.environ.get('PKG_CONFIG_PATH', '')
         self.config_files = self.__load_config_files(options.native_file)
+        self.libdir_cross_fixup()
 
     @staticmethod
     def __load_config_files(filenames):
@@ -348,6 +349,13 @@ def __load_cross_file(filename):
 
         raise MesonException('Cannot find specified cross file: ' + filename)
 
+    def libdir_cross_fixup(self):
+        # By default set libdir to "lib" when cross compiling since
+        # getting the "system default" is always wrong on multiarch
+        # platforms as it gets a value like lib/x86_64-linux-gnu.
+        if self.cross_file is not None:
+            self.builtins['libdir'].value = 'lib'
+
     def sanitize_prefix(self, prefix):
         if not os.path.isabs(prefix):
             raise MesonException('prefix value {!r} must be an absolute path'
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -4493,6 +4493,7 @@ def test_ldflag_dedup(self):
                 max_count = max(max_count, line.count(search_term))
         self.assertEqual(max_count, 1, 'Export dynamic incorrectly deduplicated.')
 
+
 class LinuxCrossArmTests(BasePlatformTests):
     '''
     Tests that cross-compilation to Linux/ARM works
@@ -4529,6 +4530,18 @@ def test_cross_file_overrides_always_args(self):
         self.assertRegex(compdb[0]['command'], '-D_FILE_OFFSET_BITS=64.*-U_FILE_OFFSET_BITS')
         self.build()
 
+    def test_cross_libdir(self):
+        # When cross compiling "libdir" should default to "lib"
+        # rather than "lib/x86_64-linux-gnu" or something like that.
+        testdir = os.path.join(self.common_test_dir, '1 trivial')
+        self.init(testdir)
+        for i in self.introspect('--buildoptions'):
+            if i['name'] == 'libdir':
+                self.assertEqual(i['value'], 'lib')
+                return
+        self.assertTrue(False, 'Option libdir not in introspect data.')
+
+
 class LinuxCrossMingwTests(BasePlatformTests):
     '''
     Tests that cross-compilation to Windows/MinGW works


Test patch: