diff options
35 files changed, 324 insertions, 102 deletions
diff --git a/ci/azure-steps.yml b/ci/azure-steps.yml index 7e0f6fe..d0f6d09 100644 --- a/ci/azure-steps.yml +++ b/ci/azure-steps.yml @@ -172,5 +172,4 @@ steps: - task: PublishBuildArtifacts@1 inputs: artifactName: $(System.JobName) - # publishing artifacts from PRs from a fork is currently blocked - condition: eq(variables['system.pullrequest.isfork'], false) + condition: not(canceled()) diff --git a/docs/markdown/Kconfig-module.md b/docs/markdown/Kconfig-module.md new file mode 100644 index 0000000..c361b5b --- /dev/null +++ b/docs/markdown/Kconfig-module.md @@ -0,0 +1,52 @@ +--- +short-description: Unstable kconfig module +authors: + - name: Mark Schulte, Paolo Bonzini + years: [2017, 2019] + has-copyright: false +... + +# Unstable kconfig module + +This module parses Kconfig output files to allow use of kconfig +configurations in meson projects. + +**Note**:Â this does not provide kconfig frontend tooling to generate a +configuration. You still need something such as kconfig frontends (see +link below) to parse your Kconfig files, and then (after you've +choosen the configuration options), output a ".config" file. + + [kconfig-frontends]: http://ymorin.is-a-geek.org/projects/kconfig-frontends + +## Usage + +The module may be imported as follows: + +``` meson +kconfig = import('unstable-kconfig') +``` + +The following functions will then be available as methods on the object +with the name `kconfig`. You can, of course, replace the name +`kconfig` with anything else. + +### kconfig.load() + +This function loads a kconfig output file and returns a dictionary object. + +`kconfig.load()` makes no attempt at parsing the values in the +file. Therefore, true boolean values will be represented as the string "y" +and integer values will have to be converted with `.to_int()`. + +Kconfig frontends usually have ".config" as the default name for the +configuration file. However, placing the configuration file in the source +directory limits the user to one configuration per source directory. +In order to allow separate configurations for each build directory, as is +the Meson standard, `meson.build` should not hardcode ".config" as the +argument to `kconfig.load()`, and should instead make the argument to +`kconfig.load()` a [project build option](Build-options.md). + +* The first (and only) argument is the path to the configuration file to + load (usually ".config"). + +**Returns**: a [dictionary object](Reference-manual.md#dictionary-object). diff --git a/docs/markdown/snippets/kconfig.md b/docs/markdown/snippets/kconfig.md new file mode 100644 index 0000000..d4d5c9b --- /dev/null +++ b/docs/markdown/snippets/kconfig.md @@ -0,0 +1,5 @@ +## New module to parse kconfig output files + +The new module `unstable-kconfig` adds the ability to parse and use kconfig output +files from `meson.build`. + diff --git a/docs/markdown/snippets/multiple-cross-files.md b/docs/markdown/snippets/multiple-cross-files.md new file mode 100644 index 0000000..de229be --- /dev/null +++ b/docs/markdown/snippets/multiple-cross-files.md @@ -0,0 +1,3 @@ +## Multipe cross files can be specified + +`--cross-file` can be passed multiple times, with the configuration files overlaying the same way as `--native-file`. diff --git a/docs/sitemap.txt b/docs/sitemap.txt index bea2a31..2e6eb68 100644 --- a/docs/sitemap.txt +++ b/docs/sitemap.txt @@ -45,6 +45,7 @@ index.md Simd-module.md Windows-module.md Cuda-module.md + Kconfig-module.md Java.md Vala.md D.md diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 3ca2f99..d69091b 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -786,8 +786,7 @@ class Backend: deps = [os.path.join(self.build_to_src, df) for df in self.interpreter.get_build_def_files()] if self.environment.is_cross_build(): - deps.append(os.path.join(self.build_to_src, - self.environment.coredata.cross_file)) + deps.extend(self.environment.coredata.cross_files) deps.append('meson-private/coredata.dat') if os.path.exists(os.path.join(self.environment.get_source_dir(), 'meson_options.txt')): deps.append(os.path.join(self.build_to_src, 'meson_options.txt')) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 9e4ba0f..7f36b7b 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -31,7 +31,7 @@ from .. import dependencies from .. import compilers from ..compilers import CompilerArgs, CCompiler, VisualStudioCCompiler, FortranCompiler from ..linkers import ArLinker -from ..mesonlib import File, MachineChoice, MesonException, OrderedSet +from ..mesonlib import File, MachineChoice, MesonException, OrderedSet, LibType from ..mesonlib import get_compiler_for_source, has_path_sep from .backends import CleanTrees from ..build import InvalidArguments @@ -2401,8 +2401,8 @@ rule FORTRAN_DEP_HACK%s # TODO The get_library_naming requirement currently excludes link targets that use d or fortran as their main linker if hasattr(linker, 'get_library_naming'): search_dirs = tuple(search_dirs) + linker.get_library_dirs(self.environment) - static_patterns = linker.get_library_naming(self.environment, 'static', strict=True) - shared_patterns = linker.get_library_naming(self.environment, 'shared', strict=True) + static_patterns = linker.get_library_naming(self.environment, LibType.STATIC, strict=True) + shared_patterns = linker.get_library_naming(self.environment, LibType.SHARED, strict=True) for libname in libs: # be conservative and record most likely shared and static resolution, because we don't know exactly # which one the linker will prefer diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 2983ce7..4294bb1 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -27,7 +27,7 @@ from . import compilers from ..mesonlib import ( EnvironmentException, MachineChoice, MesonException, Popen_safe, listify, version_compare, for_windows, for_darwin, for_cygwin, for_haiku, - for_openbsd, darwin_get_object_archs + for_openbsd, darwin_get_object_archs, LibType ) from .c_function_attributes import C_FUNC_ATTRIBUTES @@ -903,7 +903,7 @@ class CCompiler(Compiler): patterns.append(p + '{}.so.[0-9]*.[0-9]*') return patterns - def get_library_naming(self, env, libtype, strict=False): + def get_library_naming(self, env, libtype: LibType, strict=False): ''' Get library prefixes and suffixes for the target platform ordered by priority @@ -936,18 +936,17 @@ class CCompiler(Compiler): # Linux/BSDs shlibext = ['so'] # Search priority - if libtype == 'shared-static': + if libtype is LibType.PREFER_SHARED: patterns = self._get_patterns(env, prefixes, shlibext, True) patterns.extend([x for x in self._get_patterns(env, prefixes, stlibext, False) if x not in patterns]) - elif libtype == 'static-shared': + elif libtype is LibType.PREFER_STATIC: patterns = self._get_patterns(env, prefixes, stlibext, False) patterns.extend([x for x in self._get_patterns(env, prefixes, shlibext, True) if x not in patterns]) - elif libtype == 'shared': + elif libtype is LibType.SHARED: patterns = self._get_patterns(env, prefixes, shlibext, True) - elif libtype == 'static': - patterns = self._get_patterns(env, prefixes, stlibext, False) else: - raise AssertionError('BUG: unknown libtype {!r}'.format(libtype)) + assert libtype is LibType.STATIC + patterns = self._get_patterns(env, prefixes, stlibext, False) return tuple(patterns) @staticmethod @@ -1009,13 +1008,13 @@ class CCompiler(Compiler): ''' return self.sizeof('void *', '', env) == 8 - def find_library_real(self, libname, env, extra_dirs, code, libtype): + def find_library_real(self, libname, env, extra_dirs, code, libtype: LibType): # First try if we can just add the library as -l. # Gcc + co seem to prefer builtin lib dirs to -L dirs. # Only try to find std libs if no extra dirs specified. # The built-in search procedure will always favour .so and then always - # search for .a. This is only allowed if libtype is 'shared-static' - if ((not extra_dirs and libtype == 'shared-static') or + # search for .a. This is only allowed if libtype is LibType.PREFER_SHARED + if ((not extra_dirs and libtype is LibType.PREFER_SHARED) or libname in self.internal_libs): args = ['-l' + libname] largs = self.linker_to_compiler_args(self.get_allow_undefined_link_args()) @@ -1049,7 +1048,7 @@ class CCompiler(Compiler): return [trial.as_posix()] return None - def find_library_impl(self, libname, env, extra_dirs, code, libtype): + def find_library_impl(self, libname, env, extra_dirs, code, libtype: LibType): # These libraries are either built-in or invalid if libname in self.ignore_libs: return [] @@ -1065,7 +1064,7 @@ class CCompiler(Compiler): return None return value[:] - def find_library(self, libname, env, extra_dirs, libtype='shared-static'): + def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED): code = 'int main(int argc, char **argv) { return 0; }' return self.find_library_impl(libname, env, extra_dirs, code, libtype) @@ -1397,6 +1396,13 @@ class VisualStudioCCompiler(CCompiler): self.base_options = ['b_pch', 'b_ndebug', 'b_vscrt'] # FIXME add lto, pgo and the like self.target = target self.is_64 = ('x64' in target) or ('x86_64' in target) + # do some canonicalization of target machine + if 'x86_64' in target: + self.machine = 'x64' + elif '86' in target: + self.machine = 'x86' + else: + self.machine = target # Override CCompiler.get_always_args def get_always_args(self): @@ -1473,7 +1479,7 @@ class VisualStudioCCompiler(CCompiler): return ['/nologo'] def get_linker_output_args(self, outputname): - return ['/OUT:' + outputname] + return ['/MACHINE:' + self.machine, '/OUT:' + outputname] def get_linker_search_args(self, dirname): return ['/LIBPATH:' + dirname] diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 738a5c6..15234ee 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -31,7 +31,7 @@ from .compilers import ( PGICompiler ) -from mesonbuild.mesonlib import EnvironmentException, is_osx +from mesonbuild.mesonlib import EnvironmentException, is_osx, LibType class FortranCompiler(Compiler): @@ -241,7 +241,7 @@ class FortranCompiler(Compiler): def find_library_impl(self, *args): return CCompiler.find_library_impl(self, *args) - def find_library(self, libname, env, extra_dirs, libtype='shared-static'): + def find_library(self, libname, env, extra_dirs, libtype: LibType = LibType.PREFER_SHARED): code = '''program main call exit(0) end program main''' diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index fba90fa..cb50961 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -211,8 +211,8 @@ class UserFeatureOption(UserComboOption): return self.value == 'auto' -def load_configs(filenames): - """Load native files.""" +def load_configs(filenames, subdir): + """Load configuration files from a named subdirectory.""" def gen(): for f in filenames: f = os.path.expanduser(os.path.expandvars(f)) @@ -225,7 +225,7 @@ def load_configs(filenames): os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')), ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':') for path in paths: - path_to_try = os.path.join(path, 'meson', 'native', f) + path_to_try = os.path.join(path, 'meson', subdir, f) if os.path.isfile(path_to_try): yield path_to_try break @@ -265,7 +265,7 @@ class CoreData: self.compiler_options = PerMachine({}, {}, {}) self.base_options = {} self.external_preprocess_args = PerMachine({}, {}, {}) # CPPFLAGS only - self.cross_file = self.__load_cross_file(options.cross_file) + self.cross_files = self.__load_config_files(options.cross_file) self.compilers = OrderedDict() self.cross_compilers = OrderedDict() self.deps = OrderedDict() @@ -276,57 +276,19 @@ class CoreData: @staticmethod def __load_config_files(filenames): + # Need to try and make the passed filenames absolute because when the + # files are parsed later we'll have chdir()d. if not filenames: return [] filenames = [os.path.abspath(os.path.expanduser(os.path.expanduser(f))) for f in filenames] return filenames - @staticmethod - def __load_cross_file(filename): - """Try to load the cross file. - - If the filename is None return None. If the filename is an absolute - (after resolving variables and ~), return that absolute path. Next, - check if the file is relative to the current source dir. If the path - still isn't resolved do the following: - Windows: - - Error - *: - - $XDG_DATA_HOME/meson/cross (or ~/.local/share/meson/cross if - undefined) - - $XDG_DATA_DIRS/meson/cross (or - /usr/local/share/meson/cross:/usr/share/meson/cross if undefined) - - Error - - Non-Windows follows the Linux path and will honor XDG_* if set. This - simplifies the implementation somewhat. - """ - if filename is None: - return None - filename = os.path.expanduser(os.path.expandvars(filename)) - if os.path.isabs(filename): - return filename - path_to_try = os.path.abspath(filename) - if os.path.isfile(path_to_try): - return path_to_try - if sys.platform != 'win32': - paths = [ - os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')), - ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':') - for path in paths: - path_to_try = os.path.join(path, 'meson', 'cross', filename) - if os.path.isfile(path_to_try): - return path_to_try - raise MesonException('Cannot find specified cross file: ' + filename) - - raise MesonException('Cannot find specified cross file: ' + filename) - def libdir_cross_fixup(self): # By default set libdir to "lib" when cross compiling since # getting the "system default" is always wrong on multiarch # platforms as it gets a value like lib/x86_64-linux-gnu. - if self.cross_file is not None: + if self.cross_files: self.builtins['libdir'].value = 'lib' def sanitize_prefix(self, prefix): @@ -642,8 +604,8 @@ def read_cmd_line_file(build_dir, options): options.cmd_line_options = d properties = config['properties'] - if options.cross_file is None: - options.cross_file = properties.get('cross_file', None) + if not options.cross_file: + options.cross_file = ast.literal_eval(properties.get('cross_file', '[]')) if not options.native_file: # This will be a string in the form: "['first', 'second', ...]", use # literal_eval to get it into the list of strings. @@ -654,7 +616,7 @@ def write_cmd_line_file(build_dir, options): config = CmdLineFileParser() properties = {} - if options.cross_file is not None: + if options.cross_file: properties['cross_file'] = options.cross_file if options.native_file: properties['native_file'] = options.native_file diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 8bd3b68..4e61f4c 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -36,7 +36,7 @@ from ..compilers import clib_langs from ..environment import BinaryTable, Environment, MachineInfo from ..mesonlib import MachineChoice, MesonException, OrderedSet, PerMachine from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify -from ..mesonlib import Version +from ..mesonlib import Version, LibType # These must be defined in this file to avoid cyclical references. packages = {} @@ -700,7 +700,7 @@ class PkgConfigDependency(ExternalDependency): libs_found = OrderedSet() # Track not-found libraries to know whether to add library paths libs_notfound = [] - libtype = 'static' if self.static else 'shared-static' + libtype = LibType.STATIC if self.static else LibType.PREFER_SHARED # Generate link arguments for this library link_args = [] for lib in full_args: @@ -1990,6 +1990,12 @@ class ExternalProgram: # We know what python3 is, we're running on it if len(commands) > 0 and commands[0] == 'python3': commands = mesonlib.python_command + commands[1:] + else: + # Replace python3 with the actual python3 that we are using + if commands[0] == '/usr/bin/env' and commands[1] == 'python3': + commands = mesonlib.python_command + commands[2:] + elif commands[0].split('/')[-1] == 'python3': + commands = mesonlib.python_command + commands[1:] return commands + [script] except Exception as e: mlog.debug(e) diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 609899c..e211945 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -69,16 +69,6 @@ CPU_FAMILES_64_BIT = [ class MesonConfigFile: @classmethod - def parse_datafile(cls, filename): - config = configparser.ConfigParser() - try: - with open(filename, 'r') as f: - config.read_file(f, filename) - except FileNotFoundError: - raise EnvironmentException('File not found: %s.' % filename) - return cls.from_config_parser(config) - - @classmethod def from_config_parser(cls, parser: configparser.ConfigParser): out = {} # This is a bit hackish at the moment. diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index ac6e70a..d0dccf4 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -408,12 +408,13 @@ class Environment: if self.coredata.config_files is not None: config = MesonConfigFile.from_config_parser( - coredata.load_configs(self.coredata.config_files)) + coredata.load_configs(self.coredata.config_files, 'native')) self.binaries.build = BinaryTable(config.get('binaries', {})) self.paths.build = Directories(**config.get('paths', {})) - if self.coredata.cross_file is not None: - config = MesonConfigFile.parse_datafile(self.coredata.cross_file) + if self.coredata.cross_files: + config = MesonConfigFile.from_config_parser( + coredata.load_configs(self.coredata.cross_files, 'cross')) self.properties.host = Properties(config.get('properties', {}), False) self.binaries.host = BinaryTable(config.get('binaries', {}), False) if 'host_machine' in config: @@ -1179,7 +1180,7 @@ class Environment: popen_exceptions[' '.join(linker + [arg])] = e continue if '/OUT:' in out.upper() or '/OUT:' in err.upper(): - return VisualStudioLinker(linker) + return VisualStudioLinker(linker, getattr(compiler, 'machine', None)) if p.returncode == 0 and ('armar' in linker or 'armar.exe' in linker): return ArmarLinker(linker) if 'DMD32 D Compiler' in out or 'DMD64 D Compiler' in out: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 3c3cfae..08f10a2 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1493,11 +1493,11 @@ class CompilerHolder(InterpreterObject): for i in search_dirs: if not os.path.isabs(i): raise InvalidCode('Search directory %s is not an absolute path.' % i) - libtype = 'shared-static' + libtype = mesonlib.LibType.PREFER_SHARED if 'static' in kwargs: if not isinstance(kwargs['static'], bool): raise InterpreterException('static must be a boolean') - libtype = 'static' if kwargs['static'] else 'shared' + libtype = mesonlib.LibType.STATIC if kwargs['static'] else mesonlib.LibType.SHARED linkargs = self.compiler.find_library(libname, self.environment, search_dirs, libtype) if required and not linkargs: raise InterpreterException( @@ -2119,6 +2119,9 @@ class Interpreter(InterpreterBase): def holderify(self, item): if isinstance(item, list): return [self.holderify(x) for x in item] + if isinstance(item, dict): + return {k: self.holderify(v) for k, v in item.items()} + if isinstance(item, build.CustomTarget): return CustomTargetHolder(item, self) elif isinstance(item, (int, str, bool)) or item is None: diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 5432514..c6302bf 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -26,8 +26,9 @@ class StaticLinker: class VisualStudioLinker(StaticLinker): always_args = ['/NOLOGO'] - def __init__(self, exelist): + def __init__(self, exelist, machine): self.exelist = exelist + self.machine = machine def get_exelist(self): return self.exelist[:] @@ -39,7 +40,11 @@ class VisualStudioLinker(StaticLinker): return [] def get_output_args(self, target): - return ['/OUT:' + target] + args = [] + if self.machine: + args += ['/MACHINE:' + self.machine] + args += ['/OUT:' + target] + return args def get_coverage_link_args(self): return [] diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 0afc21b..25e15e4 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -1274,3 +1274,13 @@ def relpath(path, start): return os.path.relpath(path, start) except ValueError: return path + + +class LibType(Enum): + + """Enumeration for library types.""" + + SHARED = 0 + STATIC = 1 + PREFER_SHARED = 2 + PREFER_STATIC = 3 diff --git a/mesonbuild/modules/unstable_kconfig.py b/mesonbuild/modules/unstable_kconfig.py new file mode 100644 index 0000000..1639eed --- /dev/null +++ b/mesonbuild/modules/unstable_kconfig.py @@ -0,0 +1,72 @@ +# Copyright 2017, 2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from . import ExtensionModule + +from .. import mesonlib +from ..mesonlib import typeslistify +from ..interpreterbase import FeatureNew, noKwargs +from ..interpreter import InvalidCode + +import os + +class KconfigModule(ExtensionModule): + + @FeatureNew('Kconfig Module', '0.51.0') + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.snippets.add('load') + + def _load_file(self, path_to_config): + result = dict() + try: + with open(path_to_config) as f: + for line in f: + if '#' in line: + comment_idx = line.index('#') + line = line[:comment_idx] + line = line.strip() + try: + name, val = line.split('=', 1) + except ValueError: + continue + result[name.strip()] = val.strip() + except IOError as e: + raise mesonlib.MesonException('Failed to load {}: {}'.format(path_to_config, e)) + + return result + + @noKwargs + def load(self, interpreter, state, args, kwargs): + sources = typeslistify(args, (str, mesonlib.File)) + if len(sources) != 1: + raise InvalidCode('load takes only one file input.') + + s = sources[0] + if isinstance(s, mesonlib.File): + # kconfig input is processed at "meson setup" time, not during + # the build, so it cannot reside in the build directory. + if s.is_built: + raise InvalidCode('kconfig input must be a source file.') + s = s.relative_name() + + s = os.path.join(interpreter.environment.source_dir, s) + if s not in interpreter.build_def_files: + interpreter.build_def_files.append(s) + + return self._load_file(s) + + +def initialize(*args, **kwargs): + return KconfigModule(*args, **kwargs) diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 023afdb..6e8ca83 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -29,7 +29,9 @@ from .mesonlib import MesonException def add_arguments(parser): coredata.register_builtin_arguments(parser) - parser.add_argument('--cross-file', default=None, + parser.add_argument('--cross-file', + default=[], + action='append', help='File describing cross compilation environment.') parser.add_argument('--native-file', default=[], diff --git a/mesonbuild/munstable_coredata.py b/mesonbuild/munstable_coredata.py index 78f3f34..913f942 100644 --- a/mesonbuild/munstable_coredata.py +++ b/mesonbuild/munstable_coredata.py @@ -81,8 +81,9 @@ def run(options): print('Last seen PKGCONFIG enviroment variable value: ' + v) elif k == 'version': print('Meson version: ' + v) - elif k == 'cross_file': - print('Cross File: ' + (v or 'None')) + elif k == 'cross_files': + if v: + print('Cross File: ' + ' '.join(v)) elif k == 'config_files': if v: print('Native File: ' + ' '.join(v)) diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 8967a53..85f6897 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -22,6 +22,7 @@ from . import compilers forbidden_option_names = coredata.get_builtin_options() forbidden_prefixes = [lang + '_' for lang in compilers.all_languages] + ['b_', 'backend_'] +reserved_prefixes = ['cross_'] def is_invalid_name(name): if name in forbidden_option_names: @@ -29,6 +30,9 @@ def is_invalid_name(name): pref = name.split('_')[0] + '_' if pref in forbidden_prefixes: return True + if pref in reserved_prefixes: + from . import mlog + mlog.deprecation('Option uses prefix "%s", which is reserved for Meson. This will become an error in the future.' % pref) return False class OptionException(mesonlib.MesonException): diff --git a/run_project_tests.py b/run_project_tests.py index 96fe99a..467d522 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -551,6 +551,7 @@ def detect_tests_to_run(): ('failing-meson', 'failing', False), ('failing-build', 'failing build', False), ('failing-test', 'failing test', False), + ('kconfig', 'kconfig', False), ('platform-osx', 'osx', not mesonlib.is_osx()), ('platform-windows', 'windows', not mesonlib.is_windows() and not mesonlib.is_cygwin()), diff --git a/run_unittests.py b/run_unittests.py index 0b2164f..f0410ab 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -47,7 +47,7 @@ from mesonbuild.ast import AstInterpreter from mesonbuild.mesonlib import ( is_windows, is_osx, is_cygwin, is_dragonflybsd, is_openbsd, is_haiku, windows_proof_rmtree, python_command, version_compare, - BuildDirLock, Version, PerMachine + BuildDirLock, Version, PerMachine, LibType ) from mesonbuild.environment import detect_ninja from mesonbuild.mesonlib import MesonException, EnvironmentException @@ -612,7 +612,7 @@ class InternalTests(unittest.TestCase): configfile.flush() configfile.close() opts = get_fake_options() - opts.cross_file = configfilename + opts.cross_file = (configfilename,) env = get_fake_env(opts=opts) detected_value = env.need_exe_wrapper() os.unlink(configfilename) @@ -627,7 +627,7 @@ class InternalTests(unittest.TestCase): config.write(configfile) configfile.close() opts = get_fake_options() - opts.cross_file = configfilename + opts.cross_file = (configfilename,) env = get_fake_env(opts=opts) forced_value = env.need_exe_wrapper() os.unlink(configfilename) @@ -702,13 +702,13 @@ class InternalTests(unittest.TestCase): stc = patterns[platform]['static'] shrstc = shr + tuple([x for x in stc if x not in shr]) stcshr = stc + tuple([x for x in shr if x not in stc]) - p = cc.get_library_naming(env, 'shared') + p = cc.get_library_naming(env, LibType.SHARED) self.assertEqual(p, shr) - p = cc.get_library_naming(env, 'static') + p = cc.get_library_naming(env, LibType.STATIC) self.assertEqual(p, stc) - p = cc.get_library_naming(env, 'static-shared') + p = cc.get_library_naming(env, LibType.PREFER_STATIC) self.assertEqual(p, stcshr) - p = cc.get_library_naming(env, 'shared-static') + p = cc.get_library_naming(env, LibType.PREFER_SHARED) self.assertEqual(p, shrstc) # Test find library by mocking up openbsd if platform != 'openbsd': @@ -724,7 +724,7 @@ class InternalTests(unittest.TestCase): f.write('') with open(os.path.join(tmpdir, 'libfoo.so.70.0.so.1'), 'w') as f: f.write('') - found = cc.find_library_real('foo', env, [tmpdir], '', 'shared-static') + found = cc.find_library_real('foo', env, [tmpdir], '', LibType.PREFER_SHARED) self.assertEqual(os.path.basename(found[0]), 'libfoo.so.54.0') def test_find_library_patterns(self): @@ -5871,6 +5871,25 @@ class CrossFileTests(BasePlatformTests): '-Ddef_sharedstatedir=sharedstatebar', '-Ddef_sysconfdir=sysconfbar']) + def test_cross_file_dirs_chain(self): + # crossfile2 overrides crossfile overrides nativefile + testcase = os.path.join(self.unit_test_dir, '57 native file override') + self.init(testcase, default_args=False, + extra_args=['--native-file', os.path.join(testcase, 'nativefile'), + '--cross-file', os.path.join(testcase, 'crossfile'), + '--cross-file', os.path.join(testcase, 'crossfile2'), + '-Ddef_bindir=binbar2', + '-Ddef_datadir=databar', + '-Ddef_includedir=includebar', + '-Ddef_infodir=infobar', + '-Ddef_libdir=libbar', + '-Ddef_libexecdir=libexecbar', + '-Ddef_localedir=localebar', + '-Ddef_localstatedir=localstatebar', + '-Ddef_mandir=manbar', + '-Ddef_sbindir=sbinbar', + '-Ddef_sharedstatedir=sharedstatebar', + '-Ddef_sysconfdir=sysconfbar']) class TAPParserTests(unittest.TestCase): def assert_test(self, events, **kwargs): diff --git a/test cases/kconfig/1 basic/.config b/test cases/kconfig/1 basic/.config new file mode 100644 index 0000000..071d185 --- /dev/null +++ b/test cases/kconfig/1 basic/.config @@ -0,0 +1,3 @@ +CONFIG_VAL1=y +# CONFIG_VAL2 is not set +CONFIG_VAL_VAL=4 diff --git a/test cases/kconfig/1 basic/meson.build b/test cases/kconfig/1 basic/meson.build new file mode 100644 index 0000000..5dc8d19 --- /dev/null +++ b/test cases/kconfig/1 basic/meson.build @@ -0,0 +1,16 @@ +project('kconfig basic test') + +k = import('unstable-kconfig') +conf = k.load('.config') + +if not conf.has_key('CONFIG_VAL1') + error('Expected CONFIG_VAL1 to be set, but it wasn\'t') +endif + +if conf.has_key('CONFIG_VAL2') + error('Expected CONFIG_VAL2 not be set, but it was') +endif + +if conf.get('CONFIG_VAL_VAL').to_int() != 4 + error('Expected CONFIG_VAL_VAL to be 4') +endif diff --git a/test cases/kconfig/2 subdir/.config b/test cases/kconfig/2 subdir/.config new file mode 100644 index 0000000..0599d46 --- /dev/null +++ b/test cases/kconfig/2 subdir/.config @@ -0,0 +1,2 @@ +CONFIG_IS_SET=y +# CONFIG_NOT_IS_SET is not set diff --git a/test cases/kconfig/2 subdir/dir/meson.build b/test cases/kconfig/2 subdir/dir/meson.build new file mode 100644 index 0000000..12f1502 --- /dev/null +++ b/test cases/kconfig/2 subdir/dir/meson.build @@ -0,0 +1,13 @@ + +k = import('unstable-kconfig') + +conf = k.load(meson.source_root() / '.config') + +if not conf.has_key('CONFIG_IS_SET') + error('Expected CONFIG_IS_SET to be set, but it wasn\'t') +endif + +if conf.has_key('CONFIG_NOT_IS_SET') + error('Expected CONFIG_NOT_IS_SET not be set, but it was') +endif + diff --git a/test cases/kconfig/2 subdir/meson.build b/test cases/kconfig/2 subdir/meson.build new file mode 100644 index 0000000..1245b18 --- /dev/null +++ b/test cases/kconfig/2 subdir/meson.build @@ -0,0 +1,4 @@ +project('kconfig subdir test') + +# Test into sub directory +subdir('dir') diff --git a/test cases/kconfig/3 load_config files/dir/config b/test cases/kconfig/3 load_config files/dir/config new file mode 100644 index 0000000..0599d46 --- /dev/null +++ b/test cases/kconfig/3 load_config files/dir/config @@ -0,0 +1,2 @@ +CONFIG_IS_SET=y +# CONFIG_NOT_IS_SET is not set diff --git a/test cases/kconfig/3 load_config files/dir/meson.build b/test cases/kconfig/3 load_config files/dir/meson.build new file mode 100644 index 0000000..d7b8d44 --- /dev/null +++ b/test cases/kconfig/3 load_config files/dir/meson.build @@ -0,0 +1,13 @@ + +k = import('unstable-kconfig') + +conf = k.load(files('config')) + +if not conf.has_key('CONFIG_IS_SET') + error('Expected CONFIG_IS_SET to be set, but it wasn\'t') +endif + +if conf.has_key('CONFIG_NOT_IS_SET') + error('Expected CONFIG_NOT_IS_SET not be set, but it was') +endif + diff --git a/test cases/kconfig/3 load_config files/meson.build b/test cases/kconfig/3 load_config files/meson.build new file mode 100644 index 0000000..1245b18 --- /dev/null +++ b/test cases/kconfig/3 load_config files/meson.build @@ -0,0 +1,4 @@ +project('kconfig subdir test') + +# Test into sub directory +subdir('dir') diff --git a/test cases/kconfig/4 load_config builddir/config b/test cases/kconfig/4 load_config builddir/config new file mode 100644 index 0000000..0599d46 --- /dev/null +++ b/test cases/kconfig/4 load_config builddir/config @@ -0,0 +1,2 @@ +CONFIG_IS_SET=y +# CONFIG_NOT_IS_SET is not set diff --git a/test cases/kconfig/4 load_config builddir/meson.build b/test cases/kconfig/4 load_config builddir/meson.build new file mode 100644 index 0000000..93136ba --- /dev/null +++ b/test cases/kconfig/4 load_config builddir/meson.build @@ -0,0 +1,14 @@ +project('kconfig builddir test') + +k = import('unstable-kconfig') + +configure_file(input: 'config', output: 'out-config', copy: true) +conf = k.load(meson.build_root() / 'out-config') + +if not conf.has_key('CONFIG_IS_SET') + error('Expected CONFIG_IS_SET to be set, but it wasn\'t') +endif + +if conf.has_key('CONFIG_NOT_IS_SET') + error('Expected CONFIG_NOT_IS_SET not be set, but it was') +endif diff --git a/test cases/unit/57 native file override/crossfile2 b/test cases/unit/57 native file override/crossfile2 new file mode 100644 index 0000000..70946c9 --- /dev/null +++ b/test cases/unit/57 native file override/crossfile2 @@ -0,0 +1,4 @@ +[paths] +bindir = 'binbar2' + +; vim: ft=dosini diff --git a/test cases/windows/5 resources/res/dummy.c b/test cases/windows/5 resources/res/dummy.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/windows/5 resources/res/dummy.c diff --git a/test cases/windows/5 resources/res/meson.build b/test cases/windows/5 resources/res/meson.build index 6d501a2..160d651 100644 --- a/test cases/windows/5 resources/res/meson.build +++ b/test cases/windows/5 resources/res/meson.build @@ -3,3 +3,7 @@ win = import('windows') res = win.compile_resources('myres.rc', depend_files: 'sample.ico', include_directories : inc) + +# test that with MSVC tools, LIB/LINK invokes CVTRES with correct /MACHINE +static_library('reslib', res, 'dummy.c') +shared_library('shreslib', res, 'dummy.c') |