From a6164ca5a81224b7ed672401a47260f498f06e44 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 6 Feb 2020 09:10:01 -0800 Subject: [PATCH 01/13] 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 +++++ .../project_options_in_machine_files.md | 37 +++++++++ mesonbuild/coredata.py | 10 ++- mesonbuild/environment.py | 19 +++++ run_unittests.py | 83 ++++++++++++++++++- .../75 user options for subproject/.gitignore | 1 + .../meson.build | 3 + 7 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 docs/markdown/snippets/project_options_in_machine_files.md create mode 100644 test cases/unit/75 user options for subproject/.gitignore create mode 100644 test cases/unit/75 user options for subproject/meson.build 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' +``` diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index e2a69549e..49104a7ce 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -377,6 +377,7 @@ class CoreData: host_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD) self.deps = PerMachine(build_cache, host_cache) # type: PerMachine[DependencyCache] self.compiler_check_cache = OrderedDict() + # Only to print a warning if it changes between Meson invocations. self.config_files = self.__load_config_files(options, scratch_dir, 'native') self.builtin_options_libdir_cross_fixup() @@ -734,7 +735,7 @@ class CoreData: if not self.is_cross_build(): self.copy_build_options_from_regular_ones() - def set_default_options(self, default_options, subproject, env): + def set_default_options(self, default_options: T.Mapping[str, str], subproject: str, env: 'Environment') -> None: # Warn if the user is using two different ways of setting build-type # options that override each other if 'buildtype' in env.cmd_line_options and \ @@ -755,6 +756,13 @@ class CoreData: k = subproject + ':' + k cmd_line_options[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(): + if subproject: + 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: diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index a82c8f873..c872aeede 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -553,6 +553,9 @@ class Environment: # architecture, just the build and host architectures paths = PerMachineDefaultable() + # We only need one of these as project options are not per machine + user_options = {} + ## Setup build machine defaults # Will be fully initialized later using compilers later. @@ -565,12 +568,26 @@ class Environment: ## Read in native file(s) to override build machine configuration + def load_user_options(): + for section in config.keys(): + if section.endswith('project options'): + if ':' in section: + project = section.split(':')[0] + else: + project = '' + user_options[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 + # the native values if we're doing a cross build + if not self.coredata.cross_files: + load_user_options() + ## Read in cross file(s) to override host machine configuration if self.coredata.cross_files: @@ -582,6 +599,7 @@ class Environment: if 'target_machine' in config: machines.target = MachineInfo.from_literal(config['target_machine']) paths.host = Directories(**config.get('paths', {})) + load_user_options() ## "freeze" now initialized configuration, and "save" to the class. @@ -589,6 +607,7 @@ class Environment: self.binaries = binaries.default_missing() self.properties = properties.default_missing() self.paths = paths.default_missing() + self.user_options = user_options exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper') if exe_wrapper is not None: diff --git a/run_unittests.py b/run_unittests.py index 2b0e4e178..9d96ce07a 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -7672,7 +7672,10 @@ class NativeFileTests(BasePlatformTests): for section, entries in values.items(): f.write('[{}]\n'.format(section)) for k, v in entries.items(): - f.write("{}='{}'\n".format(k, v)) + if isinstance(v, bool): + f.write("{}={}\n".format(k, v)) + else: + f.write("{}='{}'\n".format(k, v)) return filename def helper_create_binary_wrapper(self, binary, dir_=None, extra_args=None, **kwargs): @@ -7996,6 +7999,54 @@ class NativeFileTests(BasePlatformTests): self.init(testcase, extra_args=['--native-file', config]) self.build() + def test_user_options(self): + testcase = os.path.join(self.common_test_dir, '43 options') + for opt, value in [('testoption', 'some other val'), ('other_one', True), + ('combo_opt', 'one'), ('array_opt', ['two']), + ('integer_opt', 0)]: + config = self.helper_create_native_file({'project options': {opt: value}}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--native-file', config]) + self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + def test_user_options_command_line_overrides(self): + testcase = os.path.join(self.common_test_dir, '43 options') + config = self.helper_create_native_file({'project options': {'other_one': True}}) + self.init(testcase, extra_args=['--native-file', config, '-Dother_one=false']) + + def test_user_options_subproject(self): + testcase = os.path.join(self.unit_test_dir, '75 user options for subproject') + + s = os.path.join(testcase, 'subprojects') + if not os.path.exists(s): + os.mkdir(s) + s = os.path.join(s, 'sub') + if not os.path.exists(s): + sub = os.path.join(self.common_test_dir, '43 options') + shutil.copytree(sub, s) + + for opt, value in [('testoption', 'some other val'), ('other_one', True), + ('combo_opt', 'one'), ('array_opt', ['two']), + ('integer_opt', 0)]: + config = self.helper_create_native_file({'project options': {'sub:{}'.format(opt): value}}) + with self.assertRaises(subprocess.CalledProcessError) as cm: + self.init(testcase, extra_args=['--native-file', config]) + self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + def test_option_bool(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': {'werror': True}}) + 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 'werror' in each['name']: + self.assertEqual(each['value'], True) + break + else: + self.fail('Did not find werror in build options?') + class CrossFileTests(BasePlatformTests): @@ -8005,6 +8056,11 @@ class CrossFileTests(BasePlatformTests): This is mainly aimed to testing overrides from cross files. """ + def setUp(self): + super().setUp() + self.current_config = 0 + self.current_wrapper = 0 + def _cross_file_generator(self, *, needs_exe_wrapper: bool = False, exe_wrapper: T.Optional[T.List[str]] = None) -> str: if is_windows(): @@ -8133,6 +8189,21 @@ class CrossFileTests(BasePlatformTests): self.init(testdir, extra_args=['--cross-file=' + name], inprocess=True) self.wipe() + def helper_create_cross_file(self, values): + """Create a config file as a temporary file. + + values should be a nested dictionary structure of {section: {key: + value}} + """ + filename = os.path.join(self.builddir, 'generated{}.config'.format(self.current_config)) + self.current_config += 1 + with open(filename, 'wt') as f: + for section, entries in values.items(): + f.write('[{}]\n'.format(section)) + for k, v in entries.items(): + f.write("{}='{}'\n".format(k, v)) + return filename + def test_cross_file_dirs(self): testcase = os.path.join(self.unit_test_dir, '60 native file override') self.init(testcase, default_args=False, @@ -8189,6 +8260,16 @@ class CrossFileTests(BasePlatformTests): '-Ddef_sharedstatedir=sharedstatebar', '-Ddef_sysconfdir=sysconfbar']) + def test_user_options(self): + # This is just a touch test for cross file, since the implementation + # shares code after loading from the files + 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.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') + + class TAPParserTests(unittest.TestCase): def assert_test(self, events, **kwargs): if 'explanation' not in kwargs: diff --git a/test cases/unit/75 user options for subproject/.gitignore b/test cases/unit/75 user options for subproject/.gitignore new file mode 100644 index 000000000..4976afc58 --- /dev/null +++ b/test cases/unit/75 user options for subproject/.gitignore @@ -0,0 +1 @@ +subprojects/* diff --git a/test cases/unit/75 user options for subproject/meson.build b/test cases/unit/75 user options for subproject/meson.build new file mode 100644 index 000000000..0bc395b4b --- /dev/null +++ b/test cases/unit/75 user options for subproject/meson.build @@ -0,0 +1,3 @@ +project('user option for subproject') + +p = subproject('sub') From 54fb61627851a0fe765d31955629ff5d7be2d064 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 3 Jun 2020 11:19:36 -0700 Subject: [PATCH 02/13] docs/Machine-files: remove duplicate Properties section --- docs/markdown/Machine-files.md | 7 ------- 1 file changed, 7 deletions(-) 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 From af763e093a8172536d96e24901b82edd2e5b2dc9 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 10 Jun 2020 10:28:21 -0700 Subject: [PATCH 03/13] mconf/mintro: use authoritative list of options from coredata This splits the directory options and non-directory options into two dicts, and then merges them later to maintain API. --- mesonbuild/coredata.py | 29 +++++++++++++++++------------ mesonbuild/mconf.py | 14 +------------- mesonbuild/mintro.py | 14 +------------- 3 files changed, 19 insertions(+), 38 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 49104a7ce..3330ae52a 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1158,23 +1158,25 @@ class BuiltinOption(T.Generic[_T, _U]): cmdline_name = self.argparse_name_to_arg(prefix + name) parser.add_argument(cmdline_name, help=h + help_suffix, **kwargs) + # Update `docs/markdown/Builtin-options.md` after changing the options below -builtin_options = OrderedDict([ - # Directories - ('prefix', BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())), - ('bindir', BuiltinOption(UserStringOption, 'Executable directory', 'bin')), - ('datadir', BuiltinOption(UserStringOption, 'Data file directory', 'share')), - ('includedir', BuiltinOption(UserStringOption, 'Header file directory', 'include')), - ('infodir', BuiltinOption(UserStringOption, 'Info page directory', 'share/info')), - ('libdir', BuiltinOption(UserStringOption, 'Library directory', default_libdir())), - ('libexecdir', BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())), - ('localedir', BuiltinOption(UserStringOption, 'Locale data directory', 'share/locale')), +BUILTIN_DIR_OPTIONS = OrderedDict([ + ('prefix', BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())), + ('bindir', BuiltinOption(UserStringOption, 'Executable directory', 'bin')), + ('datadir', BuiltinOption(UserStringOption, 'Data file directory', 'share')), + ('includedir', BuiltinOption(UserStringOption, 'Header file directory', 'include')), + ('infodir', BuiltinOption(UserStringOption, 'Info page directory', 'share/info')), + ('libdir', BuiltinOption(UserStringOption, 'Library directory', default_libdir())), + ('libexecdir', BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())), + ('localedir', BuiltinOption(UserStringOption, 'Locale data directory', 'share/locale')), ('localstatedir', BuiltinOption(UserStringOption, 'Localstate data directory', 'var')), ('mandir', BuiltinOption(UserStringOption, 'Manual page directory', 'share/man')), ('sbindir', BuiltinOption(UserStringOption, 'System executable directory', 'sbin')), ('sharedstatedir', BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')), ('sysconfdir', BuiltinOption(UserStringOption, 'Sysconf data directory', 'etc')), - # Core options +]) # type: OptionDictType + +BUILTIN_CORE_OPTIONS = OrderedDict([ ('auto_features', BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')), ('backend', BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist)), ('buildtype', BuiltinOption(UserComboOption, 'Build type to use', 'debug', @@ -1194,7 +1196,9 @@ builtin_options = OrderedDict([ ('werror', BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)), ('wrap_mode', BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback'])), ('force_fallback_for', BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])), -]) +]) # type: OptionDictType + +builtin_options = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items())) builtin_options_per_machine = OrderedDict([ ('pkg_config_path', BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])), @@ -1230,3 +1234,4 @@ forbidden_target_names = {'clean': None, 'dist': None, 'distcheck': None, } + diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 2e03cabaf..f0703559b 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -184,19 +184,7 @@ class Conf: if not self.default_values_only: print(' Build dir ', self.build_dir) - dir_option_names = ['bindir', - 'datadir', - 'includedir', - 'infodir', - 'libdir', - 'libexecdir', - 'localedir', - 'localstatedir', - 'mandir', - 'prefix', - 'sbindir', - 'sharedstatedir', - 'sysconfdir'] + dir_option_names = list(coredata.BUILTIN_DIR_OPTIONS) test_option_names = ['errorlogs', 'stdsplit'] core_option_names = [k for k in self.coredata.builtins if k not in dir_option_names + test_option_names] diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index cccedaa59..0049bbd48 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -200,19 +200,7 @@ def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> T.List[T.Di def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[str]] = None) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]: optlist = [] # type: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]] - dir_option_names = ['bindir', - 'datadir', - 'includedir', - 'infodir', - 'libdir', - 'libexecdir', - 'localedir', - 'localstatedir', - 'mandir', - 'prefix', - 'sbindir', - 'sharedstatedir', - 'sysconfdir'] + dir_option_names = list(cdata.BUILTIN_DIR_OPTIONS) test_option_names = ['errorlogs', 'stdsplit'] core_option_names = [k for k in coredata.builtins if k not in dir_option_names + test_option_names] From bbba6a7f365f8b7dc7f2d4c3ce7f3e5f4c05fc5e Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 6 Feb 2020 12:18:10 -0800 Subject: [PATCH 04/13] 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 ++++++- .../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(-) 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): From 17c8193615e5fafbbfcf99b1d028f5da36d79cc4 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 16 Jun 2020 11:11:15 -0700 Subject: [PATCH 05/13] machine-files: give better error messages about using integers --- mesonbuild/coredata.py | 12 +++++++++--- test cases/failing/106 number in combo/meson.build | 1 + .../failing/106 number in combo/nativefile.ini | 2 ++ test cases/failing/106 number in combo/test.json | 5 +++++ test cases/failing/107 bool in combo/meson.build | 1 + .../failing/107 bool in combo/meson_options.txt | 5 +++++ test cases/failing/107 bool in combo/nativefile.ini | 2 ++ test cases/failing/107 bool in combo/test.json | 5 +++++ 8 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 test cases/failing/106 number in combo/meson.build create mode 100644 test cases/failing/106 number in combo/nativefile.ini create mode 100644 test cases/failing/106 number in combo/test.json create mode 100644 test cases/failing/107 bool in combo/meson.build create mode 100644 test cases/failing/107 bool in combo/meson_options.txt create mode 100644 test cases/failing/107 bool in combo/nativefile.ini create mode 100644 test cases/failing/107 bool in combo/test.json diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 0cac02962..b7efe3002 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -161,10 +161,16 @@ class UserComboOption(UserOption[str]): def validate_value(self, value): if value not in self.choices: + if isinstance(value, bool): + _type = 'boolean' + elif isinstance(value, (int, float)): + _type = 'number' + else: + _type = 'string' optionsstring = ', '.join(['"%s"' % (item,) for item in self.choices]) - raise MesonException('Value "{}" for combo option "{}" is not one of the choices.' - ' Possible choices are: {}.'.format( - value, self.description, optionsstring)) + raise MesonException('Value "{}" (of type "{}") for combo option "{}" is not one of the choices.' + ' Possible choices are (as string): {}.'.format( + value, _type, self.description, optionsstring)) return value class UserArrayOption(UserOption[T.List[str]]): diff --git a/test cases/failing/106 number in combo/meson.build b/test cases/failing/106 number in combo/meson.build new file mode 100644 index 000000000..1a647df1a --- /dev/null +++ b/test cases/failing/106 number in combo/meson.build @@ -0,0 +1 @@ +project('number in combo') diff --git a/test cases/failing/106 number in combo/nativefile.ini b/test cases/failing/106 number in combo/nativefile.ini new file mode 100644 index 000000000..55f10fc20 --- /dev/null +++ b/test cases/failing/106 number in combo/nativefile.ini @@ -0,0 +1,2 @@ +[built-in options] +optimization = 1 diff --git a/test cases/failing/106 number in combo/test.json b/test cases/failing/106 number in combo/test.json new file mode 100644 index 000000000..a32c35894 --- /dev/null +++ b/test cases/failing/106 number in combo/test.json @@ -0,0 +1,5 @@ +{ + "stdout": [ + { "line": "test cases/failing/106 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } + ] +} diff --git a/test cases/failing/107 bool in combo/meson.build b/test cases/failing/107 bool in combo/meson.build new file mode 100644 index 000000000..c5efd67ea --- /dev/null +++ b/test cases/failing/107 bool in combo/meson.build @@ -0,0 +1 @@ +project('bool in combo') diff --git a/test cases/failing/107 bool in combo/meson_options.txt b/test cases/failing/107 bool in combo/meson_options.txt new file mode 100644 index 000000000..0c8f5de00 --- /dev/null +++ b/test cases/failing/107 bool in combo/meson_options.txt @@ -0,0 +1,5 @@ +option( + 'opt', + type : 'combo', + choices : ['true', 'false'] +) diff --git a/test cases/failing/107 bool in combo/nativefile.ini b/test cases/failing/107 bool in combo/nativefile.ini new file mode 100644 index 000000000..b423957cf --- /dev/null +++ b/test cases/failing/107 bool in combo/nativefile.ini @@ -0,0 +1,2 @@ +[project options] +opt = true diff --git a/test cases/failing/107 bool in combo/test.json b/test cases/failing/107 bool in combo/test.json new file mode 100644 index 000000000..37218e86d --- /dev/null +++ b/test cases/failing/107 bool in combo/test.json @@ -0,0 +1,5 @@ +{ + "stdout": [ + { "line": "test cases/failing/107 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } + ] +} From 1ca17dc853ece6225a46b46330e436d46d74bc4b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 10 Jun 2020 13:02:30 -0700 Subject: [PATCH 06/13] 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(-) 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 From e981798e0b5ccb53cdb94a616c9bccc20f091e6b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 16 Jun 2020 11:33:02 -0700 Subject: [PATCH 07/13] coredata: fix type annotation --- mesonbuild/coredata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index b7efe3002..e3b6dab51 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -374,7 +374,7 @@ class CoreData: self.compiler_options = PerMachine( defaultdict(dict), defaultdict(dict), - ) # : PerMachine[T.defaultdict[str, OptionDictType]] + ) # type: PerMachine[T.defaultdict[str, OptionDictType]] self.base_options = {} # type: OptionDictType self.cross_files = self.__load_config_files(options, scratch_dir, 'cross') self.compilers = PerMachine(OrderedDict(), OrderedDict()) From 601789cc7ce3692fbefe14047d8b8cc68a3d5160 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 16 Jun 2020 15:23:15 -0700 Subject: [PATCH 08/13] 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(-) 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): From 5358765806909de8a7179c7becb3ee6ae1a54215 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 19 Jun 2020 21:13:35 -0700 Subject: [PATCH 09/13] mesonlib: Add repr() methods to PerMachine classes Which is super helpful in debuggers --- mesonbuild/mesonlib.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index a43d4c4da..2c563e487 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -389,6 +389,9 @@ class PerMachine(T.Generic[_T]): unfreeze.host = None return unfreeze + def __repr__(self) -> str: + return 'PerMachine({!r}, {!r})'.format(self.build, self.host) + class PerThreeMachine(PerMachine[_T]): """Like `PerMachine` but includes `target` too. @@ -421,6 +424,9 @@ class PerThreeMachine(PerMachine[_T]): def matches_build_machine(self, machine: MachineChoice) -> bool: return self.build == self[machine] + def __repr__(self) -> str: + return 'PerThreeMachine({!r}, {!r}, {!r})'.format(self.build, self.host, self.target) + class PerMachineDefaultable(PerMachine[T.Optional[_T]]): """Extends `PerMachine` with the ability to default from `None`s. @@ -439,6 +445,9 @@ class PerMachineDefaultable(PerMachine[T.Optional[_T]]): freeze.host = freeze.build return freeze + def __repr__(self) -> str: + return 'PerMachineDefaultable({!r}, {!r})'.format(self.build, self.host) + class PerThreeMachineDefaultable(PerMachineDefaultable, PerThreeMachine[T.Optional[_T]]): """Extends `PerThreeMachine` with the ability to default from `None`s. @@ -460,6 +469,9 @@ class PerThreeMachineDefaultable(PerMachineDefaultable, PerThreeMachine[T.Option freeze.target = freeze.host return freeze + def __repr__(self) -> str: + return 'PerThreeMachineDefaultable({!r}, {!r}, {!r})'.format(self.build, self.host, self.target) + def is_sunos() -> bool: return platform.system().lower() == 'sunos' From 5db3860abf6a27b0dd4653fa8c7143f4a70df7a7 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 19 Jun 2020 10:53:20 -0700 Subject: [PATCH 10/13] push all config-file settings into coredata.set_default_options This puts all of them together, in the next patch they'll be pulled back out, but it's convenient to start that refactor by moving them all there, then moving them into env as a whole. --- mesonbuild/coredata.py | 69 ++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 99da03442..aaf31aa54 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -751,34 +751,44 @@ class CoreData: 'See: https://mesonbuild.com/Builtin-options.html#build-type-options') cmd_line_options = OrderedDict() - # 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 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 - 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(): + from . import optinterpreter + from .compilers import all_languages + if not subproject: + # 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. + for k, v in chain(default_options.items(), env.meson_options.host.get('', {}).items()): + cmd_line_options[k] = v + + # compiler options are always per-machine, but not per sub-project + if '' in env.meson_options.build: + for lang in all_languages: + prefix = '{}_'.format(lang) + for k in env.meson_options.build['']: + if k.startswith(prefix): + cmd_line_options['build.{}'.format(k)] = env.meson_options.build[subproject][k] + else: + # If the subproject options comes from a machine file, then we need to + # set the option as subproject:option + for k, v in chain(default_options.items(), env.meson_options.host.get('', {}).items(), + 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 + cmd_line_options.update(env.cmd_line_options) + env.cmd_line_options = cmd_line_options + + options = OrderedDict() # 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(): if subproject: k = '{}:{}'.format(subproject, k) - cmd_line_options[k] = v + 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)]: @@ -791,28 +801,13 @@ class CoreData: # 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: + if subproject: + template = '{s}:build.{k}' + else: + template = 'build.{k}' 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 use - cmd_line_options.update(env.cmd_line_options) - env.cmd_line_options = cmd_line_options - - # Create a subset of cmd_line_options, keeping only options for this - # subproject. Also take builtin options if it's the main project. - # Language and backend specific options will be set later when adding - # languages and setting the backend (builtin options must be set first - # to know which backend we'll use). - options = OrderedDict() + options[template.format(s=subproject, k=k)] = env.meson_options.build[subproject][k] # Some options default to environment variables if they are # unset, set those now. These will either be overwritten @@ -846,7 +841,7 @@ class CoreData: return text[len(prefix):] return text - for k, v in env.cmd_line_options.items(): + for k, v in cmd_line_options.items(): if subproject: if not k.startswith(subproject + ':'): continue From 591e6e94b9fccfc49ee7093cb21735a27fd64005 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 19 Jun 2020 17:01:10 -0700 Subject: [PATCH 11/13] Put machine file and cmd line parsing in Environment This creates a full set of option in environment that mirror those in coredata, this mirroring of the coredata structure is convenient because lookups int env (such as when initializing compilers) becomes a straight dict lookup, with no list iteration. It also means that all of the command line and machine files are read and stored in the correct order before they're ever accessed, simplifying the logic of using them. --- mesonbuild/ast/introspection.py | 2 +- mesonbuild/coredata.py | 172 ++++++++++---------------------- mesonbuild/environment.py | 130 ++++++++++++++++++++++-- mesonbuild/interpreter.py | 8 +- run_unittests.py | 61 ++++++++++- 5 files changed, 238 insertions(+), 135 deletions(-) diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py index 142c219fd..6e6927f48 100644 --- a/mesonbuild/ast/introspection.py +++ b/mesonbuild/ast/introspection.py @@ -120,7 +120,7 @@ class IntrospectionInterpreter(AstInterpreter): self.do_subproject(i) self.coredata.init_backend_options(self.backend) - options = {k: v for k, v in self.environment.cmd_line_options.items() if k.startswith('backend_')} + options = {k: v for k, v in self.environment.meson_options.host[''].items() if k.startswith('backend_')} self.coredata.set_options(options) self.func_add_languages(None, proj_langs, None) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index aaf31aa54..724e111a2 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -20,10 +20,8 @@ from pathlib import PurePath from collections import OrderedDict, defaultdict from .mesonlib import ( MesonException, EnvironmentException, MachineChoice, PerMachine, - OrderedSet, default_libdir, default_libexecdir, default_prefix, - split_args + default_libdir, default_libexecdir, default_prefix, split_args ) -from .envconfig import get_env_var_pair from .wrap import WrapMode import ast import argparse @@ -741,117 +739,54 @@ class CoreData: if not self.is_cross_build(): self.copy_build_options_from_regular_ones() - def set_default_options(self, default_options: T.Mapping[str, str], subproject: str, env: 'Environment') -> None: - # Warn if the user is using two different ways of setting build-type - # options that override each other - if 'buildtype' in env.cmd_line_options and \ - ('optimization' in env.cmd_line_options or 'debug' in env.cmd_line_options): - 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() - - from . import optinterpreter - from .compilers import all_languages - if not subproject: - # 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. - for k, v in chain(default_options.items(), env.meson_options.host.get('', {}).items()): - cmd_line_options[k] = v - - # compiler options are always per-machine, but not per sub-project - if '' in env.meson_options.build: - for lang in all_languages: - prefix = '{}_'.format(lang) - for k in env.meson_options.build['']: - if k.startswith(prefix): - cmd_line_options['build.{}'.format(k)] = env.meson_options.build[subproject][k] - else: - # If the subproject options comes from a machine file, then we need to - # set the option as subproject:option - for k, v in chain(default_options.items(), env.meson_options.host.get('', {}).items(), - 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 - cmd_line_options.update(env.cmd_line_options) - env.cmd_line_options = cmd_line_options + def set_default_options(self, default_options: 'T.OrderedDict[str, str]', subproject: str, env: 'Environment') -> None: + def make_key(key: str) -> str: + if subproject: + return '{}:{}'.format(subproject, key) + return key options = OrderedDict() - # 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(): - if subproject: - k = '{}:{}'.format(subproject, k) - options[k] = v - - # 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: - if subproject: - template = '{s}:build.{k}' + # TODO: validate these + from .compilers import all_languages, base_options + lang_prefixes = tuple('{}_'.format(l) for l in all_languages) + # split arguments that can be set now, and those that cannot so they + # can be set later, when they've been initialized. + for k, v in default_options.items(): + if k.startswith(lang_prefixes): + lang, key = k.split('_', 1) + for machine in MachineChoice: + if key not in env.compiler_options[machine][lang]: + env.compiler_options[machine][lang][key] = v + elif k in base_options: + if not subproject and k not in env.base_options: + env.base_options[k] = v else: - template = 'build.{k}' - for k in builtin_options_per_machine.keys(): - if k in env.meson_options.build[subproject]: - options[template.format(s=subproject, k=k)] = env.meson_options.build[subproject][k] - - # Some options default to environment variables if they are - # unset, set those now. These will either be overwritten - # below, or they won't. These should only be set on the first run. - for for_machine in MachineChoice: - p_env_pair = get_env_var_pair(for_machine, self.is_cross_build(), 'PKG_CONFIG_PATH') - if p_env_pair is not None: - p_env_var, p_env = p_env_pair - - # PKG_CONFIG_PATH may contain duplicates, which must be - # removed, else a duplicates-in-array-option warning arises. - p_list = list(OrderedSet(p_env.split(':'))) - - key = 'pkg_config_path' - if for_machine == MachineChoice.BUILD: - key = 'build.' + key - - if env.first_invocation: - options[key] = p_list - elif options.get(key, []) != p_list: - mlog.warning( - p_env_var + - ' environment variable has changed ' - 'between configurations, meson ignores this. ' - 'Use -Dpkg_config_path to change pkg-config search ' - 'path instead.' - ) - - def remove_prefix(text, prefix): - if text.startswith(prefix): - return text[len(prefix):] - return text - - for k, v in cmd_line_options.items(): - if subproject: - if not k.startswith(subproject + ':'): - continue - elif k not in builtin_options.keys() \ - and remove_prefix(k, 'build.') not in builtin_options_per_machine.keys(): - if ':' in k: - continue - if optinterpreter.is_invalid_name(k, log=False): + options[make_key(k)] = v + + for k, v in chain(env.meson_options.host.get('', {}).items(), + env.meson_options.host.get(subproject, {}).items()): + options[make_key(k)] = v + + for k, v in chain(env.meson_options.build.get('', {}).items(), + env.meson_options.build.get(subproject, {}).items()): + if k in builtin_options_per_machine: + options[make_key('build.{}'.format(k))] = v + + options.update({make_key(k): v for k, v in env.user_options.get(subproject, {}).items()}) + + # Some options (namely the compiler options) are not preasant in + # coredata until the compiler is fully initialized. As such, we need to + # put those options into env.meson_options, only if they're not already + # in there, as the machine files and command line have precendence. + for k, v in default_options.items(): + if k in builtin_options and not builtin_options[k].yielding: + continue + for machine in MachineChoice: + if machine is MachineChoice.BUILD and not self.is_cross_build(): continue - options[k] = v + if k not in env.meson_options[machine][subproject]: + env.meson_options[machine][subproject][k] = v self.set_options(options, subproject=subproject) @@ -867,24 +802,19 @@ class CoreData: env.is_cross_build(), env.properties[for_machine]).items(): # prefixed compiler options affect just this machine - opt_prefix = for_machine.get_prefix() - user_k = opt_prefix + lang + '_' + k - if user_k in env.cmd_line_options: - o.set_value(env.cmd_line_options[user_k]) + if k in env.compiler_options[for_machine].get(lang, {}): + o.set_value(env.compiler_options[for_machine][lang][k]) self.compiler_options[for_machine][lang].setdefault(k, o) - def process_new_compiler(self, lang: str, comp: T.Type['Compiler'], env: 'Environment') -> None: + def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None: from . import compilers self.compilers[comp.for_machine][lang] = comp - enabled_opts = [] for k, o in comp.get_options().items(): # prefixed compiler options affect just this machine - opt_prefix = comp.for_machine.get_prefix() - user_k = opt_prefix + lang + '_' + k - if user_k in env.cmd_line_options: - o.set_value(env.cmd_line_options[user_k]) + if k in env.compiler_options[comp.for_machine].get(lang, {}): + o.set_value(env.compiler_options[comp.for_machine][lang][k]) self.compiler_options[comp.for_machine][lang].setdefault(k, o) enabled_opts = [] @@ -892,8 +822,8 @@ class CoreData: if optname in self.base_options: continue oobj = compilers.base_options[optname] - if optname in env.cmd_line_options: - oobj.set_value(env.cmd_line_options[optname]) + if optname in env.base_options: + oobj.set_value(env.base_options[optname]) enabled_opts.append(optname) self.base_options[optname] = oobj self.emit_base_options_warnings(enabled_opts) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 7dfffa2f7..9830b452a 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -16,6 +16,7 @@ import os, platform, re, sys, shutil, subprocess import tempfile import shlex import typing as T +import collections from . import coredata from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, DLinker, CcrxLinker, Xc16Linker, C2000Linker, IntelVisualStudioLinker @@ -28,11 +29,13 @@ from . import mlog from .envconfig import ( BinaryTable, MachineInfo, - Properties, known_cpu_families, + Properties, known_cpu_families, get_env_var_pair, ) from . import compilers from .compilers import ( Compiler, + all_languages, + base_options, is_assembly, is_header, is_library, @@ -549,10 +552,10 @@ class Environment: properties = PerMachineDefaultable() # We only need one of these as project options are not per machine - user_options = {} + user_options = collections.defaultdict(dict) # type: T.DefaultDict[str, T.Dict[str, object]] # meson builtin options, as passed through cross or native files - meson_options = PerMachineDefaultable() + meson_options = PerMachineDefaultable() # type: PerMachineDefaultable[T.DefaultDict[str, T.Dict[str, object]]] ## Setup build machine defaults @@ -564,6 +567,13 @@ class Environment: binaries.build = BinaryTable() properties.build = Properties() + # meson base options + _base_options = {} # type: T.Dict[str, object] + + # Per language compiler arguments + compiler_options = PerMachineDefaultable() # type: PerMachineDefaultable[T.DefaultDict[str, T.Dict[str, object]]] + compiler_options.build = collections.defaultdict(dict) + ## Read in native file(s) to override build machine configuration def load_options(tag: str, store: T.Dict[str, T.Any]) -> None: @@ -573,7 +583,44 @@ class Environment: project = section.split(':')[0] else: project = '' - store[project] = config.get(section, {}) + store[project].update(config.get(section, {})) + + def split_base_options(mopts: T.DefaultDict[str, T.Dict[str, object]]) -> None: + for k, v in list(mopts.get('', {}).items()): + if k in base_options: + _base_options[k] = v + del mopts[k] + + lang_prefixes = tuple('{}_'.format(l) for l in all_languages) + def split_compiler_options(mopts: T.DefaultDict[str, T.Dict[str, object]], machine: MachineChoice) -> None: + for k, v in list(mopts.get('', {}).items()): + if k.startswith(lang_prefixes): + lang, key = k.split('_', 1) + if compiler_options[machine] is None: + compiler_options[machine] = collections.defaultdict(dict) + if lang not in compiler_options[machine]: + compiler_options[machine][lang] = collections.defaultdict(dict) + compiler_options[machine][lang][key] = v + del mopts[''][k] + + def move_compiler_options(properties: Properties, compopts: T.Dict[str, T.DefaultDict[str, object]]) -> None: + for k, v in properties.properties.copy().items(): + for lang in all_languages: + if k == '{}_args'.format(lang): + if 'args' not in compopts[lang]: + compopts[lang]['args'] = v + else: + mlog.warning('Ignoring {}_args in [properties] section for those in the [built-in options]'.format(lang)) + elif k == '{}_link_args'.format(lang): + if 'link_args' not in compopts[lang]: + compopts[lang]['link_args'] = v + else: + mlog.warning('Ignoring {}_link_args in [properties] section in favor of the [built-in options] section.') + else: + continue + mlog.deprecation('{} in the [properties] section of the machine file is deprecated, use the [built-in options] section.'.format(k)) + del properties.properties[k] + break if self.coredata.config_files is not None: config = coredata.parse_machine_files(self.coredata.config_files) @@ -584,11 +631,15 @@ class Environment: # the native values if we're doing a cross build if not self.coredata.cross_files: load_options('project options', user_options) - meson_options.build = {} + meson_options.build = collections.defaultdict(dict) 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) + if not self.coredata.cross_files: + split_base_options(meson_options.build) + split_compiler_options(meson_options.build, MachineChoice.BUILD) + move_compiler_options(properties.build, compiler_options.build) ## Read in cross file(s) to override host machine configuration @@ -601,11 +652,15 @@ class Environment: if 'target_machine' in config: machines.target = MachineInfo.from_literal(config['target_machine']) load_options('project options', user_options) - meson_options.host = {} + meson_options.host = collections.defaultdict(dict) + compiler_options.host = collections.defaultdict(dict) 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) + split_base_options(meson_options.host) + split_compiler_options(meson_options.host, MachineChoice.HOST) + move_compiler_options(properties.host, compiler_options.host) ## "freeze" now initialized configuration, and "save" to the class. @@ -614,6 +669,67 @@ class Environment: self.properties = properties.default_missing() self.user_options = user_options self.meson_options = meson_options.default_missing() + self.base_options = _base_options + self.compiler_options = compiler_options.default_missing() + + # Some options default to environment variables if they are + # unset, set those now. + + for for_machine in MachineChoice: + p_env_pair = get_env_var_pair(for_machine, self.coredata.is_cross_build(), 'PKG_CONFIG_PATH') + if p_env_pair is not None: + p_env_var, p_env = p_env_pair + + # PKG_CONFIG_PATH may contain duplicates, which must be + # removed, else a duplicates-in-array-option warning arises. + p_list = list(mesonlib.OrderedSet(p_env.split(':'))) + + key = 'pkg_config_path' + + if self.first_invocation: + # Environment variables override config + self.meson_options[for_machine][''][key] = p_list + elif self.meson_options[for_machine][''].get(key, []) != p_list: + mlog.warning( + p_env_var, + 'environment variable does not match configured', + 'between configurations, meson ignores this.', + 'Use -Dpkg_config_path to change pkg-config search', + 'path instead.' + ) + + # Read in command line and populate options + # TODO: validate all of this + all_builtins = set(coredata.builtin_options) | set(coredata.builtin_options_per_machine) | set(coredata.builtin_dir_noprefix_options) + for k, v in options.cmd_line_options.items(): + try: + subproject, k = k.split(':') + except ValueError: + subproject = '' + if k in base_options: + self.base_options[k] = v + elif k.startswith(lang_prefixes): + lang, key = k.split('_', 1) + self.compiler_options.host[lang][key] = v + elif k in all_builtins or k.startswith('backend_'): + self.meson_options.host[subproject][k] = v + elif k.startswith('build.'): + k = k.lstrip('build.') + if k in coredata.builtin_options_per_machine: + if self.meson_options.build is None: + self.meson_options.build = collections.defaultdict(dict) + self.meson_options.build[subproject][k] = v + else: + assert not k.startswith('build.') + self.user_options[subproject][k] = v + + # Warn if the user is using two different ways of setting build-type + # options that override each other + if meson_options.build and 'buildtype' in meson_options.build[''] and \ + ('optimization' in meson_options.build[''] or 'debug' in meson_options.build['']): + 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') exe_wrapper = self.lookup_binary_entry(MachineChoice.HOST, 'exe_wrapper') if exe_wrapper is not None: @@ -622,8 +738,6 @@ class Environment: else: self.exe_wrapper = None - self.cmd_line_options = options.cmd_line_options.copy() - # List of potential compilers. if mesonlib.is_windows(): # Intel C and C++ compiler is icl on Windows, but icc and icpc elsewhere. diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 317793db5..cf7f28237 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2946,6 +2946,7 @@ external dependencies (including libraries) must go to "dependencies".''') if self.is_subproject(): optname = self.subproject + ':' + optname + for opts in [ self.coredata.base_options, compilers.base_options, self.coredata.builtins, dict(self.coredata.get_prefixed_options_per_machine(self.coredata.builtins_per_machine)), @@ -3031,8 +3032,9 @@ external dependencies (including libraries) must go to "dependencies".''') if self.environment.first_invocation: self.coredata.init_backend_options(backend) - options = {k: v for k, v in self.environment.cmd_line_options.items() if k.startswith('backend_')} - self.coredata.set_options(options) + if '' in self.environment.meson_options.host: + options = {k: v for k, v in self.environment.meson_options.host[''].items() if k.startswith('backend_')} + self.coredata.set_options(options) @stringArgs @permittedKwargs(permitted_kwargs['project']) @@ -3065,7 +3067,7 @@ external dependencies (including libraries) must go to "dependencies".''') self.project_default_options = mesonlib.stringlistify(kwargs.get('default_options', [])) self.project_default_options = coredata.create_options_dict(self.project_default_options) if self.environment.first_invocation: - default_options = self.project_default_options + default_options = self.project_default_options.copy() default_options.update(self.default_project_options) self.coredata.init_builtins(self.subproject) else: diff --git a/run_unittests.py b/run_unittests.py index 7bab4088d..21eabde3e 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -8030,7 +8030,7 @@ class NativeFileTests(BasePlatformTests): for opt, value in [('testoption', 'some other val'), ('other_one', True), ('combo_opt', 'one'), ('array_opt', ['two']), ('integer_opt', 0)]: - config = self.helper_create_native_file({'project options': {'sub:{}'.format(opt): value}}) + config = self.helper_create_native_file({'sub:project options': {opt: value}}) with self.assertRaises(subprocess.CalledProcessError) as cm: self.init(testcase, extra_args=['--native-file', config]) self.assertRegex(cm.exception.stdout, r'Incorrect value to [a-z]+ option') @@ -8076,6 +8076,19 @@ class NativeFileTests(BasePlatformTests): else: self.fail('Did not find werror in build options?') + def test_builtin_options_env_overrides_conf(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_native_file({'built-in options': {'pkg_config_path': '/foo'}}) + + self.init(testcase, extra_args=['--native-file', config], override_envvars={'PKG_CONFIG_PATH': '/bar'}) + configuration = self.introspect('--buildoptions') + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/bar']) + break + else: + self.fail('Did not find pkg_config_path 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'}}) @@ -8185,6 +8198,22 @@ class NativeFileTests(BasePlatformTests): 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): @@ -8431,7 +8460,15 @@ class CrossFileTests(BasePlatformTests): 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]) + # Ensure that PKG_CONFIG_PATH is not set in the environment + with mock.patch.dict('os.environ'): + for k in ['PKG_CONFIG_PATH', 'PKG_CONFIG_PATH_FOR_BUILD']: + try: + del os.environ[k] + except KeyError: + pass + self.init(testcase, extra_args=['--cross-file', cross, '--native-file', native]) + configuration = self.introspect('--buildoptions') found = 0 for each in configuration: @@ -8452,6 +8489,26 @@ class CrossFileTests(BasePlatformTests): break self.assertEqual(found, 4, 'Did not find all sections.') + def test_builtin_options_env_overrides_conf(self): + testcase = os.path.join(self.common_test_dir, '2 cpp') + config = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/foo'}}) + cross = self.helper_create_cross_file({'built-in options': {'pkg_config_path': '/foo'}}) + + self.init(testcase, extra_args=['--native-file', config, '--cross-file', cross], + override_envvars={'PKG_CONFIG_PATH': '/bar', 'PKG_CONFIG_PATH_FOR_BUILD': '/dir'}) + configuration = self.introspect('--buildoptions') + found = 0 + for each in configuration: + if each['name'] == 'pkg_config_path': + self.assertEqual(each['value'], ['/bar']) + found += 1 + elif each['name'] == 'build.pkg_config_path': + self.assertEqual(each['value'], ['/dir']) + found += 1 + if found == 2: + break + self.assertEqual(found, 2, 'Did not find all sections.') + class TAPParserTests(unittest.TestCase): def assert_test(self, events, **kwargs): From 3a4d8dde52a5755901ec97784e9f3d883162873b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 30 Jul 2020 19:46:36 -0700 Subject: [PATCH 12/13] update version from 0.55. to 0.56 --- docs/markdown/Machine-files.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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. From 4d2a17041f0dd54001a7d32b36e75608330f41f5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 30 Jul 2020 19:46:57 -0700 Subject: [PATCH 13/13] run dircondensor.py --- run_unittests.py | 14 +++++++------- .../foolib.cmake.in | 0 .../{19 cmake file => 20 cmake file}/meson.build | 0 .../{19 cmake file => 20 cmake file}/test.json | 0 .../meson.build | 0 .../nativefile.ini | 0 .../test.json | 2 +- .../meson.build | 0 .../meson_options.txt | 0 .../nativefile.ini | 0 .../test.json | 2 +- .../client/client.c | 0 .../client/meson.build | 0 .../val1/meson.build | 0 .../val1/val1.c | 0 .../val1/val1.h | 0 .../val2/meson.build | 0 .../val2/val2.c | 0 .../val2/val2.h | 0 .../meson.build | 0 .../subprojects/flub/meson.build | 0 .../75 user options for subproject/.gitignore | 0 .../75 user options for subproject/meson.build | 0 .../meson.build | 0 .../rpathified.cpp | 0 .../yonder/meson.build | 0 .../yonder/yonder.cpp | 0 .../yonder/yonder.h | 0 .../unit/{78 wrap-git => 81 wrap-git}/meson.build | 0 .../packagefiles/wrap_git_builddef/meson.build | 0 .../subprojects/wrap_git_upstream/main.c | 0 31 files changed, 9 insertions(+), 9 deletions(-) rename test cases/cmake/{19 cmake file => 20 cmake file}/foolib.cmake.in (100%) rename test cases/cmake/{19 cmake file => 20 cmake file}/meson.build (100%) rename test cases/cmake/{19 cmake file => 20 cmake file}/test.json (100%) rename test cases/failing/{106 number in combo => 107 number in combo}/meson.build (100%) rename test cases/failing/{106 number in combo => 107 number in combo}/nativefile.ini (100%) rename test cases/failing/{106 number in combo => 107 number in combo}/test.json (77%) rename test cases/failing/{107 bool in combo => 108 bool in combo}/meson.build (100%) rename test cases/failing/{107 bool in combo => 108 bool in combo}/meson_options.txt (100%) rename test cases/failing/{107 bool in combo => 108 bool in combo}/nativefile.ini (100%) rename test cases/failing/{107 bool in combo => 108 bool in combo}/test.json (73%) rename test cases/unit/{76 pkgconfig prefixes => 77 pkgconfig prefixes}/client/client.c (100%) rename test cases/unit/{76 pkgconfig prefixes => 77 pkgconfig prefixes}/client/meson.build (100%) rename test cases/unit/{76 pkgconfig prefixes => 77 pkgconfig prefixes}/val1/meson.build (100%) rename test cases/unit/{76 pkgconfig prefixes => 77 pkgconfig prefixes}/val1/val1.c (100%) rename test cases/unit/{76 pkgconfig prefixes => 77 pkgconfig prefixes}/val1/val1.h (100%) rename test cases/unit/{76 pkgconfig prefixes => 77 pkgconfig prefixes}/val2/meson.build (100%) rename test cases/unit/{76 pkgconfig prefixes => 77 pkgconfig prefixes}/val2/val2.c (100%) rename test cases/unit/{76 pkgconfig prefixes => 77 pkgconfig prefixes}/val2/val2.h (100%) rename test cases/unit/{76 subdir libdir => 78 subdir libdir}/meson.build (100%) rename test cases/unit/{76 subdir libdir => 78 subdir libdir}/subprojects/flub/meson.build (100%) rename test cases/unit/{ => 79 user options for subproject}/75 user options for subproject/.gitignore (100%) rename test cases/unit/{ => 79 user options for subproject}/75 user options for subproject/meson.build (100%) rename test cases/unit/{77 global-rpath => 80 global-rpath}/meson.build (100%) rename test cases/unit/{77 global-rpath => 80 global-rpath}/rpathified.cpp (100%) rename test cases/unit/{77 global-rpath => 80 global-rpath}/yonder/meson.build (100%) rename test cases/unit/{77 global-rpath => 80 global-rpath}/yonder/yonder.cpp (100%) rename test cases/unit/{77 global-rpath => 80 global-rpath}/yonder/yonder.h (100%) rename test cases/unit/{78 wrap-git => 81 wrap-git}/meson.build (100%) rename test cases/unit/{78 wrap-git => 81 wrap-git}/subprojects/packagefiles/wrap_git_builddef/meson.build (100%) rename test cases/unit/{78 wrap-git => 81 wrap-git}/subprojects/wrap_git_upstream/main.c (100%) diff --git a/run_unittests.py b/run_unittests.py index 21eabde3e..6d7eba213 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -5014,7 +5014,7 @@ recommended as it is not supported on some platforms''') def test_wrap_git(self): with tempfile.TemporaryDirectory() as tmpdir: srcdir = os.path.join(tmpdir, 'src') - shutil.copytree(os.path.join(self.unit_test_dir, '78 wrap-git'), srcdir) + shutil.copytree(os.path.join(self.unit_test_dir, '81 wrap-git'), srcdir) upstream = os.path.join(srcdir, 'subprojects', 'wrap_git_upstream') upstream_uri = Path(upstream).as_uri() _git_init(upstream) @@ -6473,7 +6473,7 @@ class LinuxlikeTests(BasePlatformTests): if is_osx(): raise unittest.SkipTest('Global RPATHs via LDFLAGS not yet supported on MacOS (does anybody need it?)') - testdir = os.path.join(self.unit_test_dir, '77 global-rpath') + testdir = os.path.join(self.unit_test_dir, '80 global-rpath') oldinstalldir = self.installdir # Build and install an external library without DESTDIR. @@ -6846,7 +6846,7 @@ class LinuxlikeTests(BasePlatformTests): oldinstalldir = self.installdir # Build and install both external libraries without DESTDIR - val1dir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'val1') + val1dir = os.path.join(self.unit_test_dir, '77 pkgconfig prefixes', 'val1') val1prefix = os.path.join(oldinstalldir, 'val1') self.prefix = val1prefix self.installdir = val1prefix @@ -6857,7 +6857,7 @@ class LinuxlikeTests(BasePlatformTests): env1 = {} env1['PKG_CONFIG_PATH'] = os.path.join(val1prefix, self.libdir, 'pkgconfig') - val2dir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'val2') + val2dir = os.path.join(self.unit_test_dir, '77 pkgconfig prefixes', 'val2') val2prefix = os.path.join(oldinstalldir, 'val2') self.prefix = val2prefix self.installdir = val2prefix @@ -6869,7 +6869,7 @@ class LinuxlikeTests(BasePlatformTests): # Build, install, and run the client program env2 = {} env2['PKG_CONFIG_PATH'] = os.path.join(val2prefix, self.libdir, 'pkgconfig') - testdir = os.path.join(self.unit_test_dir, '76 pkgconfig prefixes', 'client') + testdir = os.path.join(self.unit_test_dir, '77 pkgconfig prefixes', 'client') testprefix = os.path.join(oldinstalldir, 'client') self.prefix = testprefix self.installdir = testprefix @@ -7180,7 +7180,7 @@ class LinuxCrossArmTests(BaseLinuxCrossTests): def test_cross_libdir_subproject(self): # Guard against a regression where calling "subproject" # would reset the value of libdir to its default value. - testdir = os.path.join(self.unit_test_dir, '76 subdir libdir') + testdir = os.path.join(self.unit_test_dir, '78 subdir libdir') self.init(testdir, extra_args=['--libdir=fuf']) for i in self.introspect('--buildoptions'): if i['name'] == 'libdir': @@ -8017,7 +8017,7 @@ class NativeFileTests(BasePlatformTests): self.init(testcase, extra_args=['--native-file', config, '-Dother_one=false']) def test_user_options_subproject(self): - testcase = os.path.join(self.unit_test_dir, '75 user options for subproject') + testcase = os.path.join(self.unit_test_dir, '79 user options for subproject') s = os.path.join(testcase, 'subprojects') if not os.path.exists(s): diff --git a/test cases/cmake/19 cmake file/foolib.cmake.in b/test cases/cmake/20 cmake file/foolib.cmake.in similarity index 100% rename from test cases/cmake/19 cmake file/foolib.cmake.in rename to test cases/cmake/20 cmake file/foolib.cmake.in diff --git a/test cases/cmake/19 cmake file/meson.build b/test cases/cmake/20 cmake file/meson.build similarity index 100% rename from test cases/cmake/19 cmake file/meson.build rename to test cases/cmake/20 cmake file/meson.build diff --git a/test cases/cmake/19 cmake file/test.json b/test cases/cmake/20 cmake file/test.json similarity index 100% rename from test cases/cmake/19 cmake file/test.json rename to test cases/cmake/20 cmake file/test.json diff --git a/test cases/failing/106 number in combo/meson.build b/test cases/failing/107 number in combo/meson.build similarity index 100% rename from test cases/failing/106 number in combo/meson.build rename to test cases/failing/107 number in combo/meson.build diff --git a/test cases/failing/106 number in combo/nativefile.ini b/test cases/failing/107 number in combo/nativefile.ini similarity index 100% rename from test cases/failing/106 number in combo/nativefile.ini rename to test cases/failing/107 number in combo/nativefile.ini diff --git a/test cases/failing/106 number in combo/test.json b/test cases/failing/107 number in combo/test.json similarity index 77% rename from test cases/failing/106 number in combo/test.json rename to test cases/failing/107 number in combo/test.json index a32c35894..f5aeb4e7e 100644 --- a/test cases/failing/106 number in combo/test.json +++ b/test cases/failing/107 number in combo/test.json @@ -1,5 +1,5 @@ { "stdout": [ - { "line": "test cases/failing/106 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } + { "line": "test cases/failing/107 number in combo/meson.build:1:0: ERROR: Value \"1\" (of type \"number\") for combo option \"Optimization level\" is not one of the choices. Possible choices are (as string): \"0\", \"g\", \"1\", \"2\", \"3\", \"s\"." } ] } diff --git a/test cases/failing/107 bool in combo/meson.build b/test cases/failing/108 bool in combo/meson.build similarity index 100% rename from test cases/failing/107 bool in combo/meson.build rename to test cases/failing/108 bool in combo/meson.build diff --git a/test cases/failing/107 bool in combo/meson_options.txt b/test cases/failing/108 bool in combo/meson_options.txt similarity index 100% rename from test cases/failing/107 bool in combo/meson_options.txt rename to test cases/failing/108 bool in combo/meson_options.txt diff --git a/test cases/failing/107 bool in combo/nativefile.ini b/test cases/failing/108 bool in combo/nativefile.ini similarity index 100% rename from test cases/failing/107 bool in combo/nativefile.ini rename to test cases/failing/108 bool in combo/nativefile.ini diff --git a/test cases/failing/107 bool in combo/test.json b/test cases/failing/108 bool in combo/test.json similarity index 73% rename from test cases/failing/107 bool in combo/test.json rename to test cases/failing/108 bool in combo/test.json index 37218e86d..729ad3df5 100644 --- a/test cases/failing/107 bool in combo/test.json +++ b/test cases/failing/108 bool in combo/test.json @@ -1,5 +1,5 @@ { "stdout": [ - { "line": "test cases/failing/107 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } + { "line": "test cases/failing/108 bool in combo/meson.build:1:0: ERROR: Value \"True\" (of type \"boolean\") for combo option \"opt\" is not one of the choices. Possible choices are (as string): \"true\", \"false\"." } ] } diff --git a/test cases/unit/76 pkgconfig prefixes/client/client.c b/test cases/unit/77 pkgconfig prefixes/client/client.c similarity index 100% rename from test cases/unit/76 pkgconfig prefixes/client/client.c rename to test cases/unit/77 pkgconfig prefixes/client/client.c diff --git a/test cases/unit/76 pkgconfig prefixes/client/meson.build b/test cases/unit/77 pkgconfig prefixes/client/meson.build similarity index 100% rename from test cases/unit/76 pkgconfig prefixes/client/meson.build rename to test cases/unit/77 pkgconfig prefixes/client/meson.build diff --git a/test cases/unit/76 pkgconfig prefixes/val1/meson.build b/test cases/unit/77 pkgconfig prefixes/val1/meson.build similarity index 100% rename from test cases/unit/76 pkgconfig prefixes/val1/meson.build rename to test cases/unit/77 pkgconfig prefixes/val1/meson.build diff --git a/test cases/unit/76 pkgconfig prefixes/val1/val1.c b/test cases/unit/77 pkgconfig prefixes/val1/val1.c similarity index 100% rename from test cases/unit/76 pkgconfig prefixes/val1/val1.c rename to test cases/unit/77 pkgconfig prefixes/val1/val1.c diff --git a/test cases/unit/76 pkgconfig prefixes/val1/val1.h b/test cases/unit/77 pkgconfig prefixes/val1/val1.h similarity index 100% rename from test cases/unit/76 pkgconfig prefixes/val1/val1.h rename to test cases/unit/77 pkgconfig prefixes/val1/val1.h diff --git a/test cases/unit/76 pkgconfig prefixes/val2/meson.build b/test cases/unit/77 pkgconfig prefixes/val2/meson.build similarity index 100% rename from test cases/unit/76 pkgconfig prefixes/val2/meson.build rename to test cases/unit/77 pkgconfig prefixes/val2/meson.build diff --git a/test cases/unit/76 pkgconfig prefixes/val2/val2.c b/test cases/unit/77 pkgconfig prefixes/val2/val2.c similarity index 100% rename from test cases/unit/76 pkgconfig prefixes/val2/val2.c rename to test cases/unit/77 pkgconfig prefixes/val2/val2.c diff --git a/test cases/unit/76 pkgconfig prefixes/val2/val2.h b/test cases/unit/77 pkgconfig prefixes/val2/val2.h similarity index 100% rename from test cases/unit/76 pkgconfig prefixes/val2/val2.h rename to test cases/unit/77 pkgconfig prefixes/val2/val2.h diff --git a/test cases/unit/76 subdir libdir/meson.build b/test cases/unit/78 subdir libdir/meson.build similarity index 100% rename from test cases/unit/76 subdir libdir/meson.build rename to test cases/unit/78 subdir libdir/meson.build diff --git a/test cases/unit/76 subdir libdir/subprojects/flub/meson.build b/test cases/unit/78 subdir libdir/subprojects/flub/meson.build similarity index 100% rename from test cases/unit/76 subdir libdir/subprojects/flub/meson.build rename to test cases/unit/78 subdir libdir/subprojects/flub/meson.build diff --git a/test cases/unit/75 user options for subproject/.gitignore b/test cases/unit/79 user options for subproject/75 user options for subproject/.gitignore similarity index 100% rename from test cases/unit/75 user options for subproject/.gitignore rename to test cases/unit/79 user options for subproject/75 user options for subproject/.gitignore diff --git a/test cases/unit/75 user options for subproject/meson.build b/test cases/unit/79 user options for subproject/75 user options for subproject/meson.build similarity index 100% rename from test cases/unit/75 user options for subproject/meson.build rename to test cases/unit/79 user options for subproject/75 user options for subproject/meson.build diff --git a/test cases/unit/77 global-rpath/meson.build b/test cases/unit/80 global-rpath/meson.build similarity index 100% rename from test cases/unit/77 global-rpath/meson.build rename to test cases/unit/80 global-rpath/meson.build diff --git a/test cases/unit/77 global-rpath/rpathified.cpp b/test cases/unit/80 global-rpath/rpathified.cpp similarity index 100% rename from test cases/unit/77 global-rpath/rpathified.cpp rename to test cases/unit/80 global-rpath/rpathified.cpp diff --git a/test cases/unit/77 global-rpath/yonder/meson.build b/test cases/unit/80 global-rpath/yonder/meson.build similarity index 100% rename from test cases/unit/77 global-rpath/yonder/meson.build rename to test cases/unit/80 global-rpath/yonder/meson.build diff --git a/test cases/unit/77 global-rpath/yonder/yonder.cpp b/test cases/unit/80 global-rpath/yonder/yonder.cpp similarity index 100% rename from test cases/unit/77 global-rpath/yonder/yonder.cpp rename to test cases/unit/80 global-rpath/yonder/yonder.cpp diff --git a/test cases/unit/77 global-rpath/yonder/yonder.h b/test cases/unit/80 global-rpath/yonder/yonder.h similarity index 100% rename from test cases/unit/77 global-rpath/yonder/yonder.h rename to test cases/unit/80 global-rpath/yonder/yonder.h diff --git a/test cases/unit/78 wrap-git/meson.build b/test cases/unit/81 wrap-git/meson.build similarity index 100% rename from test cases/unit/78 wrap-git/meson.build rename to test cases/unit/81 wrap-git/meson.build diff --git a/test cases/unit/78 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build b/test cases/unit/81 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build similarity index 100% rename from test cases/unit/78 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build rename to test cases/unit/81 wrap-git/subprojects/packagefiles/wrap_git_builddef/meson.build diff --git a/test cases/unit/78 wrap-git/subprojects/wrap_git_upstream/main.c b/test cases/unit/81 wrap-git/subprojects/wrap_git_upstream/main.c similarity index 100% rename from test cases/unit/78 wrap-git/subprojects/wrap_git_upstream/main.c rename to test cases/unit/81 wrap-git/subprojects/wrap_git_upstream/main.c