From a6164ca5a81224b7ed672401a47260f498f06e44 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 6 Feb 2020 09:10:01 -0800 Subject: Allow setting project options from cross or native files This allows adding a `[project options]` section to a cross or native file that contains the options defined for a project in it's meson_option.txt file. --- docs/markdown/Machine-files.md | 20 ++++++++++++ .../snippets/project_options_in_machine_files.md | 37 ++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 docs/markdown/snippets/project_options_in_machine_files.md (limited to 'docs') diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index 9011f79d7..26af44a39 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -12,6 +12,7 @@ The following sections are allowed: - binaries - paths - properties +- project options ### constants @@ -166,6 +167,25 @@ section may contain random key value pairs accessed using the The properties section can contain any variable you like, and is accessed via `meson.get_external_property`, or `meson.get_cross_property`. +### Project specific options + +*New in 0.54.0* + +Being able to set project specific options in a native or cross files can be +done using the `[project options]` section of the specific file (if doing a +cross build the options from the native file will be ignored) + +For setting options in supbprojects use the `:project options` +section instead. + +```ini +[project options] +build-tests = true + +[zlib:project options] +build-tests = false +``` + ## Loading multiple machine files Native files allow layering (cross files can be layered since meson 0.52.0). diff --git a/docs/markdown/snippets/project_options_in_machine_files.md b/docs/markdown/snippets/project_options_in_machine_files.md new file mode 100644 index 000000000..78b129aa3 --- /dev/null +++ b/docs/markdown/snippets/project_options_in_machine_files.md @@ -0,0 +1,37 @@ +## Project options can be set in native or cross files + +A new set of sections has been added to the cross and native files, `[project +options]` and `[:project options]`, where `subproject_name` +is the name of a subproject. Any options that are allowed in the project can +be set from this section. They have the lowest precedent, and will be +overwritten by command line arguments. + + +```meson +option('foo', type : 'string', value : 'foo') +``` + +```ini +[project options] +foo = 'other val' +``` + +```console +meson build --native-file my.ini +``` + +Will result in the option foo having the value `other val`, + +```console +meson build --native-file my.ini -Dfoo='different val' +``` + +Will result in the option foo having the value `different val`, + + +Subproject options are assigned like this: + +```ini +[zlib:project options] +foo = 'some val' +``` -- cgit v1.2.3 From 54fb61627851a0fe765d31955629ff5d7be2d064 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 3 Jun 2020 11:19:36 -0700 Subject: docs/Machine-files: remove duplicate Properties section --- docs/markdown/Machine-files.md | 7 ------- 1 file changed, 7 deletions(-) (limited to 'docs') diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index 26af44a39..ae0219b74 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -158,13 +158,6 @@ command line will override any options in the native file. For example, passing In addition to special data that may be specified in cross files, this section may contain random key value pairs accessed using the -`meson.get_external_property()` - -## Properties - -*New for native files in 0.54.0* - -The properties section can contain any variable you like, and is accessed via `meson.get_external_property`, or `meson.get_cross_property`. ### Project specific options -- cgit v1.2.3 From bbba6a7f365f8b7dc7f2d4c3ce7f3e5f4c05fc5e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 6 Feb 2020 12:18:10 -0800 Subject: Allow setting built-in options from cross/native files This is like the project options, but for meson builtin options. The only real differences here have to do with the differences between meson builtin options and project options. Some meson options can be set on a per-machine basis (build.pkg_config_path vs pkg_config_path) others can be set on a per-subproject basis, but should inherit the parent setting. --- cross/armcc.txt | 2 +- cross/armclang-linux.txt | 5 +- cross/armclang.txt | 2 +- cross/c2000.txt | 6 +- cross/ccrx.txt | 2 +- cross/iphone.txt | 6 +- cross/tvos.txt | 7 +- cross/ubuntu-armhf.txt | 6 +- cross/wasm.txt | 3 +- cross/xc16.txt | 2 + docs/markdown/Machine-files.md | 56 +++++++- .../snippets/project_options_in_machine_files.md | 17 ++- mesonbuild/coredata.py | 49 +++++-- mesonbuild/environment.py | 28 +++- mesonbuild/interpreter.py | 1 + run_unittests.py | 153 ++++++++++++++++++++- 16 files changed, 307 insertions(+), 38 deletions(-) (limited to 'docs') diff --git a/cross/armcc.txt b/cross/armcc.txt index c884ffa97..ae65c9e5e 100644 --- a/cross/armcc.txt +++ b/cross/armcc.txt @@ -7,7 +7,7 @@ cpp = 'armcc' ar = 'armar' strip = 'armar' -[properties] +[built-in options] # The '--cpu' option with the appropriate target type should be mentioned # to cross compile c/c++ code with armcc,. c_args = ['--cpu=Cortex-M0plus'] diff --git a/cross/armclang-linux.txt b/cross/armclang-linux.txt index 6df78d61a..10f6fa44b 100644 --- a/cross/armclang-linux.txt +++ b/cross/armclang-linux.txt @@ -12,7 +12,7 @@ # Armcc is only available in toolchain version 5. # Armclang is only available in toolchain version 6. # Start shell with /opt/arm/developmentstudio-2019.0/bin/suite_exec zsh -# Now the compilers will work. +# Now the compilers will work. [binaries] # we could set exe_wrapper = qemu-arm-static but to test the case @@ -24,8 +24,7 @@ ar = '/opt/arm/developmentstudio-2019.0/sw/ARMCompiler6.12/bin/armar' #strip = '/usr/arm-linux-gnueabihf/bin/strip' #pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' -[properties] - +[built-in options] c_args = ['--target=aarch64-arm-none-eabi'] [host_machine] diff --git a/cross/armclang.txt b/cross/armclang.txt index 955b7ef57..6146e0d74 100644 --- a/cross/armclang.txt +++ b/cross/armclang.txt @@ -7,7 +7,7 @@ cpp = 'armclang' ar = 'armar' strip = 'armar' -[properties] +[built-in options] # The '--target', '-mcpu' options with the appropriate values should be mentioned # to cross compile c/c++ code with armclang. c_args = ['--target=arm-arm-none-eabi', '-mcpu=cortex-m0plus'] diff --git a/cross/c2000.txt b/cross/c2000.txt index e624f253a..61c03109d 100644 --- a/cross/c2000.txt +++ b/cross/c2000.txt @@ -12,8 +12,7 @@ cpu_family = 'c2000' cpu = 'c28x' endian = 'little' -[properties] -needs_exe_wrapper = true +[built-in options] c_args = [ '-v28', '-ml', @@ -24,3 +23,6 @@ c_link_args = [ '\f28004x_flash.cmd'] cpp_args = [] cpp_link_args = [] + +[properties] +needs_exe_wrapper = true diff --git a/cross/ccrx.txt b/cross/ccrx.txt index 097ec068e..f1b536c3a 100644 --- a/cross/ccrx.txt +++ b/cross/ccrx.txt @@ -7,7 +7,7 @@ cpp = 'ccrx' ar = 'rlink' strip = 'rlink' -[properties] +[built-in options] # The '--cpu' option with the appropriate target type should be mentioned # to cross compile c/c++ code with ccrx,. c_args = ['-cpu=rx600'] diff --git a/cross/iphone.txt b/cross/iphone.txt index e714da54e..965940722 100644 --- a/cross/iphone.txt +++ b/cross/iphone.txt @@ -8,14 +8,14 @@ cpp = 'clang++' ar = 'ar' strip = 'strip' -[properties] -root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer' - +[built-in options] c_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] cpp_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] c_link_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] cpp_link_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] +[properties] +root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer' has_function_printf = true has_function_hfkerhisadf = false diff --git a/cross/tvos.txt b/cross/tvos.txt index dd6d5c16b..833f04bfd 100644 --- a/cross/tvos.txt +++ b/cross/tvos.txt @@ -8,14 +8,15 @@ cpp = 'clang++' ar = 'ar' strip = 'strip' -[properties] -root = '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer' - +[built-in options] c_args = ['-arch', 'arm64', '-mtvos-version-min=12.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] cpp_args = ['-arch', 'arm64', '-mtvos-version-min=12.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] c_link_args = ['-arch', 'arm64', '-mtvos-version-min=12.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] cpp_link_args = ['-arch', 'arm64', '-mtvos-version-min=12.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk'] +[properties] +root = '/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer' + has_function_printf = true has_function_hfkerhisadf = false diff --git a/cross/ubuntu-armhf.txt b/cross/ubuntu-armhf.txt index 4600c2281..69e0c8611 100644 --- a/cross/ubuntu-armhf.txt +++ b/cross/ubuntu-armhf.txt @@ -9,12 +9,14 @@ strip = '/usr/arm-linux-gnueabihf/bin/strip' pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' ld = '/usr/bin/arm-linux/gnueabihf-ld' -[properties] -root = '/usr/arm-linux-gnueabihf' +[built-in options] # Used in unit test '140 get define' c_args = ['-DMESON_TEST_ISSUE_1665=1'] cpp_args = '-DMESON_TEST_ISSUE_1665=1' +[properties] +root = '/usr/arm-linux-gnueabihf' + has_function_printf = true has_function_hfkerhisadf = false diff --git a/cross/wasm.txt b/cross/wasm.txt index a43636fde..f2d0cd7f5 100644 --- a/cross/wasm.txt +++ b/cross/wasm.txt @@ -3,8 +3,7 @@ c = '/home/jpakkane/emsdk/fastcomp/emscripten/emcc' cpp = '/home/jpakkane/emsdk/fastcomp/emscripten/em++' ar = '/home/jpakkane/emsdk/fastcomp/emscripten/emar' -[properties] - +[built-in options] c_args = ['-s', 'WASM=1', '-s', 'EXPORT_ALL=1'] c_link_args = ['-s','EXPORT_ALL=1'] cpp_args = ['-s', 'WASM=1', '-s', 'EXPORT_ALL=1'] diff --git a/cross/xc16.txt b/cross/xc16.txt index 1e673622f..c66889deb 100644 --- a/cross/xc16.txt +++ b/cross/xc16.txt @@ -14,6 +14,8 @@ endian = 'little' [properties] needs_exe_wrapper = true + +[built-in options] c_args = [ '-c', '-mcpu=33EP64MC203', diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index ae0219b74..e3de80811 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -13,6 +13,7 @@ The following sections are allowed: - paths - properties - project options +- built-in options ### constants @@ -158,17 +159,23 @@ command line will override any options in the native file. For example, passing In addition to special data that may be specified in cross files, this section may contain random key value pairs accessed using the -`meson.get_external_property`, or `meson.get_cross_property`. +`meson.get_external_property()`, or `meson.get_cross_property()`. + +*Changed in 0.55.0* putting `_args` and `_link_args` in the +properties section has been deprecated, and should be put in the built-in +options section. ### Project specific options -*New in 0.54.0* +*New in 0.55.0* + +Path options are not allowed, those must be set in the `[paths]` section. -Being able to set project specific options in a native or cross files can be +Being able to set project specific options in a cross or native file can be done using the `[project options]` section of the specific file (if doing a cross build the options from the native file will be ignored) -For setting options in supbprojects use the `:project options` +For setting options in subprojects use the `[:project options]` section instead. ```ini @@ -179,6 +186,47 @@ build-tests = true build-tests = false ``` + +### Meson built-in options + +Meson built-in options can be set the same way: + +```ini +[built-in options] +c_std = 'c99' +``` + +You can set some meson built-in options on a per-subproject basis, such as +`default_library` and `werror`. The order of precedence is: +1) Command line +2) Machine file +3) Build system definitions + +```ini +[zlib:built-in options] +default_library = 'static' +werror = false +``` + +Options set on a per-subproject basis will inherit the +option from the parent if the parent has a setting but the subproject +doesn't, even when there is a default set meson language. + +```ini +[built-in options] +default_library = 'static' +``` + +will make subprojects use default_library as static. + +Some options can be set on a per-machine basis (in other words, the value of +the build machine can be different than the host machine in a cross compile). +In these cases the values from both a cross file and a native file are used. + +An incomplete list of options is: +- pkg_config_path +- cmake_prefix_path + ## Loading multiple machine files Native files allow layering (cross files can be layered since meson 0.52.0). diff --git a/docs/markdown/snippets/project_options_in_machine_files.md b/docs/markdown/snippets/project_options_in_machine_files.md index 78b129aa3..8dab9515d 100644 --- a/docs/markdown/snippets/project_options_in_machine_files.md +++ b/docs/markdown/snippets/project_options_in_machine_files.md @@ -1,4 +1,4 @@ -## Project options can be set in native or cross files +## Project and built-in options can be set in native or cross files A new set of sections has been added to the cross and native files, `[project options]` and `[:project options]`, where `subproject_name` @@ -35,3 +35,18 @@ Subproject options are assigned like this: [zlib:project options] foo = 'some val' ``` + +Additionally meson level options can be set in the same way, using the +`[built-in options]` section. + +```ini +[built-in options] +c_std = 'c99' +``` + +These options can also be set on a per-subproject basis, although only +`default_library` and `werror` can currently be set: +```ini +[zlib:built-in options] +default_library = 'static' +``` diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 3330ae52a..0cac02962 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -361,15 +361,15 @@ class CoreData: self.install_guid = str(uuid.uuid4()).upper() self.target_guids = {} self.version = version - self.builtins = {} # : OptionDictType + self.builtins = {} # type: OptionDictType self.builtins_per_machine = PerMachine({}, {}) - self.backend_options = {} # : OptionDictType - self.user_options = {} # : OptionDictType + self.backend_options = {} # type: OptionDictType + self.user_options = {} # type: OptionDictType self.compiler_options = PerMachine( defaultdict(dict), defaultdict(dict), ) # : PerMachine[T.defaultdict[str, OptionDictType]] - self.base_options = {} # : OptionDictType + self.base_options = {} # type: OptionDictType self.cross_files = self.__load_config_files(options, scratch_dir, 'cross') self.compilers = PerMachine(OrderedDict(), OrderedDict()) @@ -743,19 +743,28 @@ class CoreData: mlog.warning('Recommend using either -Dbuildtype or -Doptimization + -Ddebug. ' 'Using both is redundant since they override each other. ' 'See: https://mesonbuild.com/Builtin-options.html#build-type-options') + cmd_line_options = OrderedDict() - # Set project default_options as if they were passed to the cmdline. + # Set default options as if they were passed to the command line. # Subprojects can only define default for user options and not yielding # builtin option. from . import optinterpreter - for k, v in default_options.items(): + for k, v in chain(default_options.items(), env.meson_options.host.get('', {}).items()): if subproject: if (k not in builtin_options or builtin_options[k].yielding) \ and optinterpreter.is_invalid_name(k, log=False): continue - k = subproject + ':' + k cmd_line_options[k] = v + # IF the subproject options comes from a machine file, then we need to + # set the option as subproject:option + if subproject: + for k, v in env.meson_options.host.get(subproject, {}).items(): + if (k not in builtin_options or builtin_options[k].yielding) \ + and optinterpreter.is_invalid_name(k, log=False): + continue + cmd_line_options['{}:{}'.format(subproject, k)] = v + # load the values for user options out of the appropriate machine file, # then overload the command line for k, v in env.user_options.get(subproject, {}).items(): @@ -768,8 +777,32 @@ class CoreData: if v is not None: cmd_line_options[k] = v + from .compilers import all_languages + # Report that [properties]c_args + for lang in all_languages: + for args in ['{}_args'.format(lang), '{}_link_args'.format(lang)]: + msg = ('{} in the [properties] section of the machine file is deprecated, ' + 'use the [built-in options] section.') + if args in env.properties.host or args in env.properties.build: + mlog.deprecation(msg.format(args)) + + # Currently we don't support any options that are both per-subproject + # and per-machine, but when we do this will need to account for that. + # For cross builds we need to get the build specifc options + if env.meson_options.host != env.meson_options.build and subproject in env.meson_options.build: + for k in builtin_options_per_machine.keys(): + if k in env.meson_options.build[subproject]: + cmd_line_options['build.{}'.format(k)] = env.meson_options.build[subproject][k] + + # compiler options are always per-machine + for lang in all_languages: + prefix = '{}_'.format(lang) + for k in env.meson_options.build[subproject]: + if k.startswith(prefix): + cmd_line_options['build.{}'.format(k)] = env.meson_options.build[subproject][k] + # Override all the above defaults using the command-line arguments - # actually passed to us + # actually passed to use cmd_line_options.update(env.cmd_line_options) env.cmd_line_options = cmd_line_options diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index c872aeede..dc674fde1 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -556,6 +556,9 @@ class Environment: # We only need one of these as project options are not per machine user_options = {} + # meson builtin options, as passed through cross or native files + meson_options = PerMachineDefaultable() + ## Setup build machine defaults # Will be fully initialized later using compilers later. @@ -568,14 +571,15 @@ class Environment: ## Read in native file(s) to override build machine configuration - def load_user_options(): + def load_options(tag: str, store: T.Dict[str, T.Any]) -> None: for section in config.keys(): - if section.endswith('project options'): + if section.endswith(tag): if ':' in section: project = section.split(':')[0] else: project = '' - user_options[project] = config.get(section, {}) + store[project] = config.get(section, {}) + if self.coredata.config_files is not None: config = coredata.parse_machine_files(self.coredata.config_files) @@ -586,7 +590,9 @@ class Environment: # Don't run this if there are any cross files, we don't want to use # the native values if we're doing a cross build if not self.coredata.cross_files: - load_user_options() + load_options('project options', user_options) + meson_options.build = {} + load_options('built-in options', meson_options.build) ## Read in cross file(s) to override host machine configuration @@ -599,7 +605,9 @@ class Environment: if 'target_machine' in config: machines.target = MachineInfo.from_literal(config['target_machine']) paths.host = Directories(**config.get('paths', {})) - load_user_options() + load_options('project options', user_options) + meson_options.host = {} + load_options('built-in options', meson_options.host) ## "freeze" now initialized configuration, and "save" to the class. @@ -608,6 +616,16 @@ class Environment: self.properties = properties.default_missing() self.paths = paths.default_missing() self.user_options = user_options + self.meson_options = meson_options.default_missing() + + # Ensure that no paths are passed via built-in options: + if '' in self.meson_options.host: + for each in coredata.BUILTIN_DIR_OPTIONS.keys(): + # These are not per-subdirectory and probably never will be + if each in self.meson_options.host['']: + raise EnvironmentException( + 'Invalid entry {} in [built-in options] section. ' + 'Use the [paths] section instead.'.format(each)) exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper') if exe_wrapper is not None: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 45813c1e1..317793db5 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2791,6 +2791,7 @@ external dependencies (including libraries) must go to "dependencies".''') default_options = mesonlib.stringlistify(kwargs.get('default_options', [])) default_options = coredata.create_options_dict(default_options) + if dirname == '': raise InterpreterException('Subproject dir name must not be empty.') if dirname[0] == '.': diff --git a/run_unittests.py b/run_unittests.py index 9d96ce07a..bce0bda78 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -7672,8 +7672,10 @@ class NativeFileTests(BasePlatformTests): for section, entries in values.items(): f.write('[{}]\n'.format(section)) for k, v in entries.items(): - if isinstance(v, bool): + if isinstance(v, (bool, int, float)): f.write("{}={}\n".format(k, v)) + elif isinstance(v, list): + f.write("{}=[{}]\n".format(k, ', '.join(["'{}'".format(w) for w in v]))) else: f.write("{}='{}'\n".format(k, v)) return filename @@ -8047,6 +8049,108 @@ class NativeFileTests(BasePlatformTests): else: self.fail('Did not find werror in build options?') + def test_option_integer(self): + # Bools are allowed to be unquoted + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({'built-in options': {'unity_size': 100}}) + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + # Test that no-per subproject options are inherited from the parent + if 'unity_size' in each['name']: + self.assertEqual(each['value'], 100) + break + else: + self.fail('Did not find unity_size in build options?') + + def test_builtin_options(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_native_file({'built-in options': {'cpp_std': 'c++14'}}) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++14') + break + else: + self.fail('Did not find werror in build options?') + + def test_builtin_options_subprojects(self): + testcase = os.path.join(self.common_test_dir, '102 subproject subdir') + config = self.helper_create_native_file({'built-in options': {'default_library': 'both', 'c_args': ['-Dfoo']}, 'sub:built-in options': {'default_library': 'static'}}) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + # Test that no-per subproject options are inherited from the parent + if 'c_args' in each['name']: + # This path will be hit twice, once for build and once for host, + self.assertEqual(each['value'], ['-Dfoo']) + found += 1 + elif each['name'] == 'default_library': + self.assertEqual(each['value'], 'both') + found += 1 + elif each['name'] == 'sub:default_library': + self.assertEqual(each['value'], 'static') + found += 1 + self.assertEqual(found, 4, 'Did not find all three sections') + + def test_builtin_options_subprojects_overrides_buildfiles(self): + # If the buildfile says subproject(... default_library: shared), ensure that's overwritten + testcase = os.path.join(self.common_test_dir, '230 persubproject options') + config = self.helper_create_native_file({'sub2:built-in options': {'default_library': 'shared'}}) + + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--native-file', config]) + self.assertIn(cm.exception.stdout, 'Parent should override default_library') + + def test_builtin_options_subprojects_inherits_parent_override(self): + # If the buildfile says subproject(... default_library: shared), ensure that's overwritten + testcase = os.path.join(self.common_test_dir, '230 persubproject options') + config = self.helper_create_native_file({'built-in options': {'default_library': 'both'}}) + + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--native-file', config]) + self.assertIn(cm.exception.stdout, 'Parent should override default_library') + + def test_builtin_options_compiler_properties(self): + # the properties section can have lang_args, and those need to be + # overwritten by the built-in options + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'c_args': ['-DFOO']}, + 'properties': {'c_args': ['-DBAR']}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'c_args': + self.assertEqual(each['value'], ['-DFOO']) + break + else: + self.fail('Did not find c_args in build options?') + + def test_builtin_options_compiler_properties_legacy(self): + # The legacy placement in properties is still valid if a 'built-in + # options' setting is present, but doesn't have the lang_args + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'default_library': 'static'}, + 'properties': {'c_args': ['-DBAR']}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'c_args': + self.assertEqual(each['value'], ['-DBAR']) + break + else: + self.fail('Did not find c_args in build options?') + class CrossFileTests(BasePlatformTests): @@ -8266,9 +8370,54 @@ class CrossFileTests(BasePlatformTests): testcase = os.path.join(self.common_test_dir, '43 options') config = self.helper_create_cross_file({'project options': {'testoption': 'some other value'}}) with self.assertRaises(subprocess.CalledProcessError) as cm: - self.init(testcase, extra_args=['--native-file', config]) + self.init(testcase, extra_args=['--cross-file', config]) self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + def test_builtin_options(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_cross_file({'built-in options': {'cpp_std': 'c++14'}}) + + self.init(testcase, extra_args=['--cross-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++14') + break + else: + self.fail('No c++ standard set?') + + def test_builtin_options_per_machine(self): + """Test options that are allowed to be set on a per-machine basis. + + Such options could be passed twice, once for the build machine, and + once for the host machine. I've picked pkg-config path, but any would + do that can be set for both. + """ + testcase = os.path.join(self.common_test_dir, '2 cpp') + cross = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/cross/path', 'cpp_std': 'c++17'}}) + native = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/native/path', 'cpp_std': 'c++14'}}) + + self.init(testcase, extra_args=['--cross-file', cross, '--native-file', native]) + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/cross/path']) + found += 1 + elif each['name'] == 'cpp_std': + self.assertEqual(each['value'], 'c++17') + found += 1 + elif each['name'] == 'build.pkg_config_path': + self.assertEqual(each['value'], ['/native/path']) + found += 1 + elif each['name'] == 'build.cpp_std': + self.assertEqual(each['value'], 'c++14') + found += 1 + + if found == 4: + break + self.assertEqual(found, 4, 'Did not find all sections.') + class TAPParserTests(unittest.TestCase): def assert_test(self, events, **kwargs): -- cgit v1.2.3 From 1ca17dc853ece6225a46b46330e436d46d74bc4b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 10 Jun 2020 13:02:30 -0700 Subject: docs/machine-files: Add a section on data types This attempts to clarify the usage of strings and arrays, as well as document the boolean type that has been exposed via the project and built-in options --- docs/markdown/Machine-files.md | 48 +++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'docs') diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index e3de80811..9affdca89 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -5,6 +5,37 @@ documentation on the common values used by both, for the specific values of one or the other see the [cross compilation](Cross-compilation.md) and [native environments](Native-environments.md). +## Data Types + +There are four basic data types in a machine file: +- strings +- arrays +- booleans +- integers + +A string is specified single quoted: +```ini +[section] +option1 = 'false' +option2 = '2' +``` + +An array is enclosed in square brackets, and must consist of strings or booleans +```ini +[section] +option = ['value'] +``` + +A boolean must be either `true` or `false`, and unquoted. +```ini +option = false +``` + +An integer must be either an unquoted numeric constant; +```ini +option = 42 +``` + ## Sections The following sections are allowed: @@ -90,14 +121,16 @@ a = 'Hello' ### Binaries The binaries section contains a list of binaries. These can be used -internally by meson, or by the `find_program` function: +internally by meson, or by the `find_program` function. + +These values must be either strings or an array of strings Compilers and linkers are defined here using `` and `_ld`. `_ld` is special because it is compiler specific. For compilers like gcc and clang which are used to invoke the linker this is a value to pass to their "choose the linker" argument (-fuse-ld= in this case). For compilers like MSVC and Clang-Cl, this is the path to a linker for meson to invoke, -such as `link.exe` or `lld-link.exe`. Support for ls is *new in 0.53.0* +such as `link.exe` or `lld-link.exe`. Support for `ld` is *new in 0.53.0* *changed in 0.53.1* the `ld` variable was replaced by `_ld`, because it *regressed a large number of projects. in 0.53.0 the `ld` variable was used @@ -115,8 +148,8 @@ llvm-config = '/usr/lib/llvm8/bin/llvm-config' Cross example: ```ini -c = '/usr/bin/i586-mingw32msvc-gcc' -cpp = '/usr/bin/i586-mingw32msvc-g++' +c = ['ccache', '/usr/bin/i586-mingw32msvc-gcc'] +cpp = ['ccache', '/usr/bin/i586-mingw32msvc-g++'] c_ld = 'gold' cpp_ld = 'gold' ar = '/usr/i586-mingw32msvc/bin/ar' @@ -140,7 +173,7 @@ An incomplete list of internally used programs that can be overridden here is: ### Paths and Directories As of 0.50.0 paths and directories such as libdir can be defined in the native -file in a paths section +and cross files in a paths section. These should be strings ```ini [paths] @@ -186,7 +219,6 @@ build-tests = true build-tests = false ``` - ### Meson built-in options Meson built-in options can be set the same way: @@ -230,9 +262,9 @@ An incomplete list of options is: ## Loading multiple machine files Native files allow layering (cross files can be layered since meson 0.52.0). -More than one native file can be loaded, with values from a previous file being +More than one file can be loaded, with values from a previous file being overridden by the next. The intention of this is not overriding, but to allow -composing native files. This composition is done by passing the command line +composing files. This composition is done by passing the command line argument multiple times: ```console -- cgit v1.2.3 From 601789cc7ce3692fbefe14047d8b8cc68a3d5160 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 16 Jun 2020 15:23:15 -0700 Subject: machine-files: deprecate the paths section --- docs/markdown/Machine-files.md | 4 +++- mesonbuild/coredata.py | 5 ----- mesonbuild/envconfig.py | 40 ---------------------------------------- mesonbuild/environment.py | 26 +++++++------------------- run_unittests.py | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 65 deletions(-) (limited to 'docs') diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index 9affdca89..60c4dd560 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -172,8 +172,10 @@ An incomplete list of internally used programs that can be overridden here is: ### Paths and Directories +*Deprecated in 0.55.0* use the built-in section instead. + As of 0.50.0 paths and directories such as libdir can be defined in the native -and cross files in a paths section. These should be strings +and cross files in a paths section. These should be strings. ```ini [paths] diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index e3b6dab51..99da03442 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -778,11 +778,6 @@ class CoreData: k = '{}:{}'.format(subproject, k) cmd_line_options[k] = v - # Override project default_options using conf files (cross or native) - for k, v in env.paths.host: - if v is not None: - cmd_line_options[k] = v - from .compilers import all_languages # Report that [properties]c_args for lang in all_languages: diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 219b62ec8..9402d38de 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -407,43 +407,3 @@ class BinaryTable: if command is not None and (len(command) == 0 or len(command[0].strip()) == 0): command = None return command - -class Directories: - - """Data class that holds information about directories for native and cross - builds. - """ - - def __init__(self, bindir: T.Optional[str] = None, datadir: T.Optional[str] = None, - includedir: T.Optional[str] = None, infodir: T.Optional[str] = None, - libdir: T.Optional[str] = None, libexecdir: T.Optional[str] = None, - localedir: T.Optional[str] = None, localstatedir: T.Optional[str] = None, - mandir: T.Optional[str] = None, prefix: T.Optional[str] = None, - sbindir: T.Optional[str] = None, sharedstatedir: T.Optional[str] = None, - sysconfdir: T.Optional[str] = None): - self.bindir = bindir - self.datadir = datadir - self.includedir = includedir - self.infodir = infodir - self.libdir = libdir - self.libexecdir = libexecdir - self.localedir = localedir - self.localstatedir = localstatedir - self.mandir = mandir - self.prefix = prefix - self.sbindir = sbindir - self.sharedstatedir = sharedstatedir - self.sysconfdir = sysconfdir - - def __contains__(self, key: str) -> bool: - return hasattr(self, key) - - def __getitem__(self, key: str) -> T.Optional[str]: - # Mypy can't figure out what to do with getattr here, so we'll case for it - return T.cast(T.Optional[str], getattr(self, key)) - - def __setitem__(self, key: str, value: T.Optional[str]) -> None: - setattr(self, key, value) - - def __iter__(self) -> T.Iterator[T.Tuple[str, str]]: - return iter(self.__dict__.items()) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index dc674fde1..7dfffa2f7 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -27,7 +27,7 @@ from .mesonlib import ( from . import mlog from .envconfig import ( - BinaryTable, Directories, MachineInfo, + BinaryTable, MachineInfo, Properties, known_cpu_families, ) from . import compilers @@ -548,11 +548,6 @@ class Environment: # Misc other properties about each machine. properties = PerMachineDefaultable() - # Store paths for native and cross build files. There is no target - # machine information here because nothing is installed for the target - # architecture, just the build and host architectures - paths = PerMachineDefaultable() - # We only need one of these as project options are not per machine user_options = {} @@ -580,11 +575,9 @@ class Environment: project = '' store[project] = config.get(section, {}) - if self.coredata.config_files is not None: config = coredata.parse_machine_files(self.coredata.config_files) binaries.build = BinaryTable(config.get('binaries', {})) - paths.build = Directories(**config.get('paths', {})) properties.build = Properties(config.get('properties', {})) # Don't run this if there are any cross files, we don't want to use @@ -592,6 +585,9 @@ class Environment: if not self.coredata.cross_files: load_options('project options', user_options) meson_options.build = {} + if config.get('paths') is not None: + mlog.deprecation('The [paths] section is deprecated, use the [built-in options] section instead.') + load_options('paths', meson_options.build) load_options('built-in options', meson_options.build) ## Read in cross file(s) to override host machine configuration @@ -604,9 +600,11 @@ class Environment: machines.host = MachineInfo.from_literal(config['host_machine']) if 'target_machine' in config: machines.target = MachineInfo.from_literal(config['target_machine']) - paths.host = Directories(**config.get('paths', {})) load_options('project options', user_options) meson_options.host = {} + if config.get('paths') is not None: + mlog.deprecation('The [paths] section is deprecated, use the [built-in options] section instead.') + load_options('paths', meson_options.host) load_options('built-in options', meson_options.host) ## "freeze" now initialized configuration, and "save" to the class. @@ -614,19 +612,9 @@ class Environment: self.machines = machines.default_missing() self.binaries = binaries.default_missing() self.properties = properties.default_missing() - self.paths = paths.default_missing() self.user_options = user_options self.meson_options = meson_options.default_missing() - # Ensure that no paths are passed via built-in options: - if '' in self.meson_options.host: - for each in coredata.BUILTIN_DIR_OPTIONS.keys(): - # These are not per-subdirectory and probably never will be - if each in self.meson_options.host['']: - raise EnvironmentException( - 'Invalid entry {} in [built-in options] section. ' - 'Use the [paths] section instead.'.format(each)) - exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper') if exe_wrapper is not None: from .dependencies import ExternalProgram diff --git a/run_unittests.py b/run_unittests.py index bce0bda78..7bab4088d 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -8151,6 +8151,40 @@ class NativeFileTests(BasePlatformTests): else: self.fail('Did not find c_args in build options?') + def test_builtin_options_paths(self): + # the properties section can have lang_args, and those need to be + # overwritten by the built-in options + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'bindir': 'foo'}, + 'paths': {'bindir': 'bar'}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'bindir': + self.assertEqual(each['value'], 'foo') + break + else: + self.fail('Did not find bindir in build options?') + + def test_builtin_options_paths_legacy(self): + testcase = os.path.join(self.common_test_dir, '1 trivial') + config = self.helper_create_native_file({ + 'built-in options': {'default_library': 'static'}, + 'paths': {'bindir': 'bar'}, + }) + + self.init(testcase, extra_args=['--native-file', config]) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'bindir': + self.assertEqual(each['value'], 'bar') + break + else: + self.fail('Did not find bindir in build options?') + class CrossFileTests(BasePlatformTests): -- cgit v1.2.3 From 3a4d8dde52a5755901ec97784e9f3d883162873b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 30 Jul 2020 19:46:36 -0700 Subject: update version from 0.55. to 0.56 --- docs/markdown/Machine-files.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/markdown/Machine-files.md b/docs/markdown/Machine-files.md index 60c4dd560..5ac66a8ef 100644 --- a/docs/markdown/Machine-files.md +++ b/docs/markdown/Machine-files.md @@ -48,7 +48,7 @@ The following sections are allowed: ### constants -*Since 0.55.0* +*Since 0.56.0* String and list concatenation is supported using the `+` operator, joining paths is supported using the `/` operator. @@ -172,7 +172,7 @@ An incomplete list of internally used programs that can be overridden here is: ### Paths and Directories -*Deprecated in 0.55.0* use the built-in section instead. +*Deprecated in 0.56.0* use the built-in section instead. As of 0.50.0 paths and directories such as libdir can be defined in the native and cross files in a paths section. These should be strings. @@ -196,13 +196,13 @@ In addition to special data that may be specified in cross files, this section may contain random key value pairs accessed using the `meson.get_external_property()`, or `meson.get_cross_property()`. -*Changed in 0.55.0* putting `_args` and `_link_args` in the +*Changed in 0.56.0* putting `_args` and `_link_args` in the properties section has been deprecated, and should be put in the built-in options section. ### Project specific options -*New in 0.55.0* +*New in 0.56.0* Path options are not allowed, those must be set in the `[paths]` section. -- cgit v1.2.3