Repository: mesonbuild/meson

Issue:
Prefix-dependent types for sysconfdir, etc, do not work with default_options: in project()
Specifically, [this](http://mesonbuild.com/Release-notes-for-0-44-0.html#prefixdependent-defaults-for-sysconfdir-localstatedir-and-sharedstatedir) does not work:

```meson
project('testprefix', 'c', default_options: ['prefix=/usr'])
```

```console
$ meson _build
$ meson configure _build
...
Directories:
  Option         Current Value  Description
  ------         -------------  -----------
  prefix         /usr           Installation prefix.
...
  sysconfdir     etc            Sysconf data directory.
  localstatedir  /var/local     Localstate data directory.
  sharedstatedir /var/local/lib Architecture-independent data directory.
...
```

However, passing `--prefix=/usr` works as expected.

Reported by @williamh on IRC.


Discussion:

Resolving patch:
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1813,9 +1813,18 @@ def parse_default_options(self, default_options):
             if coredata.is_builtin_option(key):
                 if self.subproject != '':
                     continue # Only the master project is allowed to set global options.
+                # If this was set on the command line, do not override.
                 if not self.environment.had_argument_for(key):
                     self.coredata.set_builtin_option(key, value)
-                # If this was set on the command line, do not override.
+                    # If we are setting the prefix, then other options which
+                    # have prefix-dependent defaults need their value updating,
+                    # if they haven't been explicitly set (i.e. have their
+                    # default value)
+                    if key == 'prefix':
+                        for option in coredata.builtin_dir_noprefix_options:
+                            if not (self.environment.had_argument_for(option) or
+                                    any([k.startswith(option + '=') for k in default_options])):
+                                self.coredata.set_builtin_option(option, coredata.get_builtin_option_default(option, value))
             else:
                 # Option values set with subproject() default_options override those
                 # set in project() default_options.
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -789,6 +789,45 @@ def test_prefix_dependent_defaults(self):
                     self.assertEqual(value, expected[prefix][name])
             self.wipe()
 
+    def test_default_options_prefix_dependent_defaults(self):
+        '''
+        Tests that setting a prefix in default_options in project() sets prefix
+        dependent defaults for other options, and that those defaults can
+        be overridden in default_options or by the command line.
+        '''
+        testdir = os.path.join(self.common_test_dir, '173 default options prefix dependent defaults')
+        expected = {
+            '':
+            {'prefix':         '/usr',
+             'sysconfdir':     '/etc',
+             'localstatedir':  '/var',
+             'sharedstatedir': '/sharedstate'},
+            '--prefix=/usr':
+            {'prefix':         '/usr',
+             'sysconfdir':     '/etc',
+             'localstatedir':  '/var',
+             'sharedstatedir': '/sharedstate'},
+            '--sharedstatedir=/var/state':
+            {'prefix':         '/usr',
+             'sysconfdir':     '/etc',
+             'localstatedir':  '/var',
+             'sharedstatedir': '/var/state'},
+            '--sharedstatedir=/var/state --prefix=/usr --sysconfdir=sysconf':
+            {'prefix':         '/usr',
+             'sysconfdir':     'sysconf',
+             'localstatedir':  '/var',
+             'sharedstatedir': '/var/state'},
+        }
+        for args in expected:
+            self.init(testdir, args.split(), default_args=False)
+            opts = self.introspect('--buildoptions')
+            for opt in opts:
+                name = opt['name']
+                value = opt['value']
+                if name in expected[args]:
+                    self.assertEqual(value, expected[args][name])
+            self.wipe()
+
     def test_static_library_overwrite(self):
         '''
         Tests that static libraries are never appended to, always overwritten.


Test patch:
diff --git a/test cases/common/173 default options prefix dependent defaults/meson.build b/test cases/common/173 default options prefix dependent defaults/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/common/173 default options prefix dependent defaults/meson.build	
@@ -0,0 +1 @@
+project('default options prefix dependent defaults ', 'c', default_options : ['sharedstatedir=/sharedstate', 'prefix=/usr'])