diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2020-07-01 18:14:34 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-01 18:14:34 +0300 |
commit | 026e386ec2bd79fbf4fcd21e93df19c5a22f3ebf (patch) | |
tree | ce997fb9df71fa4463f746c1c787168147839392 /mesonbuild/interpreter.py | |
parent | 14cc2efcfef9a404498b3532ffa8130cc092f6f6 (diff) | |
parent | 576493982da325a739f04e5455ef0643b49d94f1 (diff) | |
download | meson-026e386ec2bd79fbf4fcd21e93df19c5a22f3ebf.zip meson-026e386ec2bd79fbf4fcd21e93df19c5a22f3ebf.tar.gz meson-026e386ec2bd79fbf4fcd21e93df19c5a22f3ebf.tar.bz2 |
Merge pull request #6902 from xclaesse/auto-fallback
Implicit dependency fallback when a subproject wrap or dir exists
Diffstat (limited to 'mesonbuild/interpreter.py')
-rw-r--r-- | mesonbuild/interpreter.py | 114 |
1 files changed, 83 insertions, 31 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 487bdd6..12d6cde 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -2779,10 +2779,9 @@ external dependencies (including libraries) must go to "dependencies".''') self.subproject_dir, dirname)) return subproject - subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir) - r = wrap.Resolver(subproject_dir_abs, self.coredata.get_builtin_option('wrap_mode'), current_subproject=self.subproject) + r = self.environment.wrap_resolver try: - resolved = r.resolve(dirname, method) + resolved = r.resolve(dirname, method, self.subproject) except wrap.WrapException as e: subprojdir = os.path.join(self.subproject_dir, r.directory) if isinstance(e, wrap.WrapNotFoundException): @@ -2798,7 +2797,7 @@ external dependencies (including libraries) must go to "dependencies".''') raise e subdir = os.path.join(self.subproject_dir, resolved) - subdir_abs = os.path.join(subproject_dir_abs, resolved) + subdir_abs = os.path.join(self.environment.get_source_dir(), subdir) os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True) self.global_args_frozen = True @@ -3062,6 +3061,10 @@ external dependencies (including libraries) must go to "dependencies".''') self.subproject_dir = spdirname self.build.subproject_dir = self.subproject_dir + if not self.is_subproject(): + wrap_mode = self.coredata.get_builtin_option('wrap_mode') + subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir) + self.environment.wrap_resolver = wrap.Resolver(subproject_dir_abs, wrap_mode) self.build.projects[self.subproject] = proj_name mlog.log('Project name:', mlog.bold(proj_name)) @@ -3248,7 +3251,7 @@ external dependencies (including libraries) must go to "dependencies".''') return success - def program_from_file_for(self, for_machine, prognames, silent): + def program_from_file_for(self, for_machine, prognames): for p in unholder(prognames): if isinstance(p, mesonlib.File): continue # Always points to a local (i.e. self generated) file. @@ -3287,15 +3290,13 @@ external dependencies (including libraries) must go to "dependencies".''') if progobj.found(): return progobj - def program_from_overrides(self, command_names, silent=False): + def program_from_overrides(self, command_names, extra_info): for name in command_names: if not isinstance(name, str): continue if name in self.build.find_overrides: exe = self.build.find_overrides[name] - if not silent: - mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'), - '(overridden: %s)' % exe.description()) + extra_info.append(mlog.blue('(overriden)')) return ExternalProgramHolder(exe, self.subproject, self.backend) return None @@ -3313,40 +3314,75 @@ external dependencies (including libraries) must go to "dependencies".''') % name) self.build.find_overrides[name] = exe + def notfound_program(self, args): + return ExternalProgramHolder(dependencies.NonExistingExternalProgram(' '.join(args)), self.subproject) + # TODO update modules to always pass `for_machine`. It is bad-form to assume # the host machine. def find_program_impl(self, args, for_machine: MachineChoice = MachineChoice.HOST, required=True, silent=True, wanted='', search_dirs=None): - if not isinstance(args, list): - args = [args] + args = mesonlib.listify(args) - progobj = self.program_from_overrides(args, silent=silent) + extra_info = [] + progobj = self.program_lookup(args, for_machine, required, search_dirs, extra_info) if progobj is None: - progobj = self.program_from_file_for(for_machine, args, silent=silent) - if progobj is None: - progobj = self.program_from_system(args, search_dirs, silent=silent) - if progobj is None and args[0].endswith('python3'): - prog = dependencies.ExternalProgram('python3', mesonlib.python_command, silent=True) - progobj = ExternalProgramHolder(prog, self.subproject) - if required and (progobj is None or not progobj.found()): - raise InvalidArguments('Program(s) {!r} not found or not executable'.format(args)) - if progobj is None: - return ExternalProgramHolder(dependencies.NonExistingExternalProgram(' '.join(args)), self.subproject) - # Only store successful lookups - self.store_name_lookups(args) + progobj = self.notfound_program(args) + + if not progobj.found(): + mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO')) + if required: + m = 'Program {!r} not found' + raise InterpreterException(m.format(progobj.get_name())) + return progobj + if wanted: version = progobj.get_version(self) is_found, not_found, found = mesonlib.version_compare_many(version, wanted) if not is_found: mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'), - 'found {!r} but need:'.format(version), - ', '.join(["'{}'".format(e) for e in not_found])) + 'found', mlog.normal_cyan(version), 'but need:', + mlog.bold(', '.join(["'{}'".format(e) for e in not_found]))) if required: m = 'Invalid version of program, need {!r} {!r} found {!r}.' - raise InvalidArguments(m.format(progobj.get_name(), not_found, version)) - return ExternalProgramHolder(dependencies.NonExistingExternalProgram(' '.join(args)), self.subproject) + raise InterpreterException(m.format(progobj.get_name(), not_found, version)) + return self.notfound_program(args) + extra_info.insert(0, mlog.normal_cyan(version)) + + # Only store successful lookups + self.store_name_lookups(args) + mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.green('YES'), *extra_info) + return progobj + + def program_lookup(self, args, for_machine, required, search_dirs, extra_info): + progobj = self.program_from_overrides(args, extra_info) + if progobj: + return progobj + + fallback = None + wrap_mode = self.coredata.get_builtin_option('wrap_mode') + if wrap_mode != WrapMode.nofallback: + fallback = self.environment.wrap_resolver.find_program_provider(args) + if fallback and wrap_mode == WrapMode.forcefallback: + return self.find_program_fallback(fallback, args, required, extra_info) + + progobj = self.program_from_file_for(for_machine, args) + if progobj is None: + progobj = self.program_from_system(args, search_dirs, silent=True) + if progobj is None and args[0].endswith('python3'): + prog = dependencies.ExternalProgram('python3', mesonlib.python_command, silent=True) + progobj = ExternalProgramHolder(prog, self.subproject) if prog.found() else None + if progobj is None and fallback and required: + progobj = self.find_program_fallback(fallback, args, required, extra_info) + return progobj + def find_program_fallback(self, fallback, args, required, extra_info): + mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program', + mlog.bold(' '.join(args))) + sp_kwargs = { 'required': required } + self.do_subproject(fallback, 'meson', sp_kwargs) + return self.program_from_overrides(args, extra_info) + @FeatureNewKwargs('find_program', '0.53.0', ['dirs']) @FeatureNewKwargs('find_program', '0.52.0', ['version']) @FeatureNewKwargs('find_program', '0.49.0', ['disabler']) @@ -3359,7 +3395,7 @@ external dependencies (including libraries) must go to "dependencies".''') disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) if disabled: mlog.log('Program', mlog.bold(' '.join(args)), 'skipped: feature', mlog.bold(feature), 'disabled') - return ExternalProgramHolder(dependencies.NonExistingExternalProgram(' '.join(args)), self.subproject) + return self.notfound_program(args) search_dirs = extract_search_dirs(kwargs) wanted = mesonlib.stringlistify(kwargs.get('version', [])) @@ -3453,8 +3489,12 @@ external dependencies (including libraries) must go to "dependencies".''') raise DependencyException(m.format(display_name)) return DependencyHolder(cached_dep, self.subproject) else: - m = 'Subproject {} did not override dependency {}' - raise DependencyException(m.format(subproj_path, display_name)) + if required: + m = 'Subproject {} did not override dependency {}' + raise DependencyException(m.format(subproj_path, display_name)) + mlog.log('Dependency', mlog.bold(display_name), 'from subproject', + mlog.bold(subproj_path), 'found:', mlog.red('NO')) + return self.notfound_dependency() if subproject.found(): self.verify_fallback_consistency(dirname, varname, cached_dep) dep = self.subprojects[dirname].get_variable_method([varname], {}) @@ -3549,6 +3589,18 @@ external dependencies (including libraries) must go to "dependencies".''') return self.notfound_dependency() has_fallback = 'fallback' in kwargs + if not has_fallback and name: + # Add an implicit fallback if we have a wrap file or a directory with the same name, + # but only if this dependency is required. It is common to first check for a pkg-config, + # then fallback to use find_library() and only afterward check again the dependency + # with a fallback. If the fallback has already been configured then we have to use it + # even if the dependency is not required. + provider = self.environment.wrap_resolver.find_dep_provider(name) + dirname = mesonlib.listify(provider)[0] + if provider and (required or dirname in self.subprojects): + kwargs['fallback'] = provider + has_fallback = True + if 'default_options' in kwargs and not has_fallback: mlog.warning('The "default_options" keyworg argument does nothing without a "fallback" keyword argument.', location=self.current_node) |