aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2017-09-29 10:07:29 -0700
committerDylan Baker <dylan@pnwbakers.com>2017-11-29 14:14:41 -0800
commitc9351ce30c03d107279090da7825096951a705d3 (patch)
treea9bf94236755986b2f69d2ef297e339c3c898561
parent7c779a76df9b8a4dd466b120f817b50f857081fa (diff)
downloadmeson-c9351ce30c03d107279090da7825096951a705d3.zip
meson-c9351ce30c03d107279090da7825096951a705d3.tar.gz
meson-c9351ce30c03d107279090da7825096951a705d3.tar.bz2
Add new array type option
This exposes the already existing UserStringArrayOption class through the meson_options.txt. The intention is to provide a way for projects to take list/array type arguments and validate that all of the elements in that array are valid without using complex looping constructrs.
-rw-r--r--docs/markdown/Build-options.md37
-rw-r--r--docs/markdown/snippets/option-array-type.md17
-rw-r--r--mesonbuild/coredata.py33
-rw-r--r--mesonbuild/optinterpreter.py16
-rwxr-xr-xrun_unittests.py47
-rw-r--r--test cases/common/166 array option/meson.build17
-rw-r--r--test cases/common/166 array option/meson_options.txt19
-rw-r--r--test cases/common/47 options/meson.build5
-rw-r--r--test cases/common/47 options/meson_options.txt1
-rw-r--r--test cases/unit/18 array option/meson.build15
-rw-r--r--test cases/unit/18 array option/meson_options.txt20
11 files changed, 208 insertions, 19 deletions
diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md
index cb7b19e..f05eb7b 100644
--- a/docs/markdown/Build-options.md
+++ b/docs/markdown/Build-options.md
@@ -16,18 +16,37 @@ Here is a simple option file.
option('someoption', type : 'string', value : 'optval', description : 'An option')
option('other_one', type : 'boolean', value : false)
option('combo_opt', type : 'combo', choices : ['one', 'two', 'three'], value : 'three')
+option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two'])
```
-This demonstrates the three basic option types and their usage. String
-option is just a free form string and a boolean option is,
-unsurprisingly, true or false. The combo option can have any value
-from the strings listed in argument `choices`. If `value` is not set,
-it defaults to empty string for strings, `true` for booleans or the
-first element in a combo. You can specify `description`, which is a
-free form piece of text describing the option. It defaults to option
-name.
+All types allow a `description` value to be set describing the option, if no
+option is set then the name of the option will be used instead.
-These options are accessed in Meson code with the `get_option` function.
+### Strings
+
+The string type is a free form string. If the default value is not set then an
+empty string will be used as the default.
+
+### Booleans
+
+Booleans may have values of either `true` or `false`. If not default value is
+supplied then `true` will be used as the default.
+
+### Combos
+
+A combo allows any one of the values in the `choices` parameter to be selected.
+If no default value is set then the first value will be the default.
+
+### Arrays
+
+Arrays allow one or more of the values in the `choices` parameter to be selected.
+If the `value` parameter is unset then the values of `choices` will be used as
+the default.
+
+This type is new in version 0.44.0
+
+
+## Using build options
```meson
optval = get_option('opt_name')
diff --git a/docs/markdown/snippets/option-array-type.md b/docs/markdown/snippets/option-array-type.md
new file mode 100644
index 0000000..f073dc1
--- /dev/null
+++ b/docs/markdown/snippets/option-array-type.md
@@ -0,0 +1,17 @@
+# An array type for user options
+
+Previously to have an option that took more than one value a string value would
+have to be created and split, but validating this was difficult. A new array type
+has been added to the meson_options.txt for this case. It works like a 'combo', but
+allows more than one option to be passed. When used on the command line (with -D),
+values are passed as a comma separated list.
+
+```meson
+option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one'])
+```
+
+These can be overwritten on the command line,
+
+```meson
+meson _build -Darray_opt=two,three
+```
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 401211a..af5a19a 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -127,24 +127,37 @@ class UserComboOption(UserOption):
class UserStringArrayOption(UserOption):
def __init__(self, name, description, value, **kwargs):
super().__init__(name, description, kwargs.get('choices', []))
- self.set_value(value)
-
- def validate(self, value):
- if isinstance(value, str):
- if not value.startswith('['):
- raise MesonException('Valuestring does not define an array: ' + value)
- newvalue = ast.literal_eval(value)
+ self.set_value(value, user_input=False)
+
+ def validate(self, value, user_input):
+ # User input is for options defined on the command line (via -D
+ # options). Users should put their input in as a comma separated
+ # string, but for defining options in meson_options.txt the format
+ # should match that of a combo
+ if not user_input:
+ if isinstance(value, str):
+ if not value.startswith('['):
+ raise MesonException('Valuestring does not define an array: ' + value)
+ newvalue = ast.literal_eval(value)
+ else:
+ newvalue = value
else:
- newvalue = value
+ assert isinstance(value, str)
+ newvalue = [v.strip() for v in value.split(',')]
if not isinstance(newvalue, list):
raise MesonException('"{0}" should be a string array, but it is not'.format(str(newvalue)))
for i in newvalue:
if not isinstance(i, str):
raise MesonException('String array element "{0}" is not a string.'.format(str(newvalue)))
+ if self.choices:
+ bad = [x for x in newvalue if x not in self.choices]
+ if bad:
+ raise MesonException('Options "{}" are not in allowed choices: "{}"'.format(
+ ', '.join(bad), ', '.join(self.choices)))
return newvalue
- def set_value(self, newvalue):
- self.value = self.validate(newvalue)
+ def set_value(self, newvalue, user_input=True):
+ self.value = self.validate(newvalue, user_input)
def validate_value(self, value):
self.validate(value)
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index 01dd036..22a263e 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -84,9 +84,25 @@ def ComboParser(name, description, kwargs):
raise OptionException('Combo choice elements must be strings.')
return coredata.UserComboOption(name, description, choices, kwargs.get('value', choices[0]))
+@permitted_kwargs({'value', 'choices'})
+def string_array_parser(name, description, kwargs):
+ if 'choices' not in kwargs:
+ raise OptionException('Array option missing "choices" keyword.')
+ choices = kwargs['choices']
+ if not isinstance(choices, list):
+ raise OptionException('Array choices must be an array.')
+ for i in choices:
+ if not isinstance(i, str):
+ raise OptionException('Array choice elements must be strings.')
+ value = kwargs.get('value', choices)
+ if not isinstance(value, list):
+ raise OptionException('Array choices must be passed as an array.')
+ return coredata.UserStringArrayOption(name, description, value, choices=choices)
+
option_types = {'string': StringParser,
'boolean': BooleanParser,
'combo': ComboParser,
+ 'array': string_array_parser,
}
class OptionInterpreter:
diff --git a/run_unittests.py b/run_unittests.py
index 91a71ce..42f4e19 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -1562,6 +1562,53 @@ int main(int argc, char **argv) {
cargs = ['-I' + incdir.as_posix()]
self.assertEqual(foo_dep.get_compile_args(), cargs)
+ def test_array_option_change(self):
+ def get_opt():
+ opts = self.introspect('--buildoptions')
+ for x in opts:
+ if x.get('name') == 'list':
+ return x
+ raise Exception(opts)
+
+ expected = {
+ 'name': 'list',
+ 'description': 'list',
+ 'type': 'stringarray',
+ 'value': ['foo', 'bar'],
+ }
+ tdir = os.path.join(self.unit_test_dir, '18 array option')
+ self.init(tdir)
+ original = get_opt()
+ self.assertDictEqual(original, expected)
+
+ expected['value'] = ['oink', 'boink']
+ self.setconf('-Dlist=oink,boink')
+ changed = get_opt()
+ self.assertEqual(changed, expected)
+
+ def test_array_option_bad_change(self):
+ def get_opt():
+ opts = self.introspect('--buildoptions')
+ for x in opts:
+ if x.get('name') == 'list':
+ return x
+ raise Exception(opts)
+
+ expected = {
+ 'name': 'list',
+ 'description': 'list',
+ 'type': 'stringarray',
+ 'value': ['foo', 'bar'],
+ }
+ tdir = os.path.join(self.unit_test_dir, '18 array option')
+ self.init(tdir)
+ original = get_opt()
+ self.assertDictEqual(original, expected)
+ with self.assertRaises(subprocess.CalledProcessError):
+ self.setconf('-Dlist=bad')
+ changed = get_opt()
+ self.assertDictEqual(changed, expected)
+
class FailureTests(BasePlatformTests):
'''
diff --git a/test cases/common/166 array option/meson.build b/test cases/common/166 array option/meson.build
new file mode 100644
index 0000000..bfcde7c
--- /dev/null
+++ b/test cases/common/166 array option/meson.build
@@ -0,0 +1,17 @@
+# Copyright © 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+project('stringarray default options')
+
+assert(get_option('array') == ['foo', 'bar'], 'Default value for array is not equal to choices')
diff --git a/test cases/common/166 array option/meson_options.txt b/test cases/common/166 array option/meson_options.txt
new file mode 100644
index 0000000..7ed0ac1
--- /dev/null
+++ b/test cases/common/166 array option/meson_options.txt
@@ -0,0 +1,19 @@
+# Copyright © 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+option(
+ 'array',
+ type : 'array',
+ choices : ['foo', 'bar'],
+)
diff --git a/test cases/common/47 options/meson.build b/test cases/common/47 options/meson.build
index 2a764f0..863703c 100644
--- a/test cases/common/47 options/meson.build
+++ b/test cases/common/47 options/meson.build
@@ -12,6 +12,11 @@ if get_option('combo_opt') != 'combo'
error('Incorrect value to combo option.')
endif
+if get_option('array_opt') != ['one', 'two']
+ message(get_option('array_opt'))
+ error('Incorrect value for array option')
+endif
+
# If the default changes, update test cases/unit/13 reconfigure
if get_option('b_lto') != false
error('Incorrect value in base option.')
diff --git a/test cases/common/47 options/meson_options.txt b/test cases/common/47 options/meson_options.txt
index 653dd75..8978d44 100644
--- a/test cases/common/47 options/meson_options.txt
+++ b/test cases/common/47 options/meson_options.txt
@@ -1,3 +1,4 @@
option('testoption', type : 'string', value : 'optval', description : 'An option to do something')
option('other_one', type : 'boolean', value : false)
option('combo_opt', type : 'combo', choices : ['one', 'two', 'combo'], value : 'combo')
+option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two'])
diff --git a/test cases/unit/18 array option/meson.build b/test cases/unit/18 array option/meson.build
new file mode 100644
index 0000000..2b44181
--- /dev/null
+++ b/test cases/unit/18 array option/meson.build
@@ -0,0 +1,15 @@
+# Copyright © 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+project('array option test')
diff --git a/test cases/unit/18 array option/meson_options.txt b/test cases/unit/18 array option/meson_options.txt
new file mode 100644
index 0000000..0ccdcc4
--- /dev/null
+++ b/test cases/unit/18 array option/meson_options.txt
@@ -0,0 +1,20 @@
+# Copyright © 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+option(
+ 'list',
+ type : 'array',
+ value : ['foo', 'bar'],
+ choices : ['foo', 'bar', 'oink', 'boink'],
+)