diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md index f05eb7b90..815a662df 100644 --- a/docs/markdown/Build-options.md +++ b/docs/markdown/Build-options.md @@ -16,32 +16,38 @@ 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('free_array_opt', type : 'array', value : ['one', 'two']) option('array_opt', type : 'array', choices : ['one', 'two', 'three'], value : ['one', 'two']) ``` -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. +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. ### 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. +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. +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. +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. +Arrays represent an array of strings. By default the array can contain +arbitrary strings. To limit the possible values that can used set the +`choices` parameter. Meson will then only allow the value array to +contain strings that are in the given list. The array may be +empty. The `value` parameter specifies the default value of the option +and if it is unset then the values of `choices` will be used as the +default. This type is new in version 0.44.0 @@ -61,9 +67,9 @@ prefix = get_option('prefix') ``` It should be noted that you can not set option values in your Meson -scripts. They have to be set externally with the `meson configure` command -line tool. Running `meson configure` without arguments in a build dir shows -you all options you can set. +scripts. They have to be set externally with the `meson configure` +command line tool. Running `meson configure` without arguments in a +build dir shows you all options you can set. To change their values use the `-D` option: @@ -72,5 +78,26 @@ option: $ meson configure -Doption=newvalue ``` +Setting the value of arrays is a bit special. If you only pass a +single string, then it is considered to have all values separated by +commas. Thus invoking the following command: -**NOTE:** If you cannot call `meson configure` you likely have a old version of Meson. In that case you can call `mesonconf` instead, but that is deprecated in newer versions +```console +$ meson configure -Darray_opt=foo,bar +``` + +would set the value to an array of two elements, `foo` and `bar`. + +If you need to have commas in your string values, then you need to +pass the value with proper shell quoting like this: + +```console +$ meson configure "-Doption=['a,b', 'c,d']" +``` + +The inner values must always be single quotes and the outer ones +double quotes. + +**NOTE:** If you cannot call `meson configure` you likely have a old + version of Meson. In that case you can call `mesonconf` instead, but + that is deprecated in newer versions diff --git a/docs/markdown/snippets/option-array-type.md b/docs/markdown/snippets/option-array-type.md index f073dc1aa..9eb1312fa 100644 --- a/docs/markdown/snippets/option-array-type.md +++ b/docs/markdown/snippets/option-array-type.md @@ -3,8 +3,9 @@ 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. +allows more than one option to be passed. The values can optionally be validated +against a list of valid values. 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']) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 7fbf18ab0..376570c08 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -132,7 +132,7 @@ class UserStringArrayOption(UserOption): 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 + # options). Users can 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: @@ -144,7 +144,10 @@ class UserStringArrayOption(UserOption): newvalue = value else: assert isinstance(value, str) - newvalue = [v.strip() for v in value.split(',')] + if value.startswith('['): + newvalue = ast.literal_eval(value) + else: + 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: diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 22a263e72..3cca2394f 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -86,15 +86,17 @@ def ComboParser(name, description, kwargs): @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 'choices' in kwargs: + 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) + else: + choices = None + value = kwargs.get('value', []) if not isinstance(value, list): raise OptionException('Array choices must be passed as an array.') return coredata.UserStringArrayOption(name, description, value, choices=choices) diff --git a/run_unittests.py b/run_unittests.py index 9bf712c54..943410792 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1611,6 +1611,25 @@ int main(int argc, char **argv) { changed = get_opt() self.assertDictEqual(changed, expected) + def opt_has(self, name, value): + res = self.introspect('--buildoptions') + found = False + for i in res: + if i['name'] == name: + self.assertEqual(i['value'], value) + found = True + break + self.assertTrue(found, "Array option not found in introspect data.") + + def test_free_stringarray_setting(self): + testdir = os.path.join(self.common_test_dir, '47 options') + self.init(testdir) + self.opt_has('free_array_opt', []) + self.setconf('-Dfree_array_opt=foo,bar', will_build=False) + self.opt_has('free_array_opt', ['foo', 'bar']) + self.setconf("-Dfree_array_opt=['a,b', 'c,d']", will_build=False) + self.opt_has('free_array_opt', ['a,b', 'c,d']) + class FailureTests(BasePlatformTests): ''' diff --git a/test cases/common/47 options/meson_options.txt b/test cases/common/47 options/meson_options.txt index 8978d44f5..6bd034676 100644 --- a/test cases/common/47 options/meson_options.txt +++ b/test cases/common/47 options/meson_options.txt @@ -2,3 +2,4 @@ option('testoption', type : 'string', value : 'optval', description : 'An option 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']) +option('free_array_opt', type : 'array')