diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2019-06-06 21:55:55 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-06 21:55:55 +0300 |
commit | 266b297515f0e6d0e864564a2fc2f079e829a033 (patch) | |
tree | 79d0cacab38ea2919ee52786ac601aa7ba80fe10 /mesonbuild/interpreter.py | |
parent | 7561926a70e1920c6ff8754ee1a66ab0bc3ff431 (diff) | |
parent | 9a9ea1434ab4d204d73503a61d5c1a044ce07366 (diff) | |
download | meson-266b297515f0e6d0e864564a2fc2f079e829a033.zip meson-266b297515f0e6d0e864564a2fc2f079e829a033.tar.gz meson-266b297515f0e6d0e864564a2fc2f079e829a033.tar.bz2 |
Merge pull request #4969 from mensinda/cmakeSubProject
CMake subprojects
Diffstat (limited to 'mesonbuild/interpreter.py')
-rw-r--r-- | mesonbuild/interpreter.py | 89 |
1 files changed, 70 insertions, 19 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index a945f70..7c17e1c 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -31,6 +31,7 @@ from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabl from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs from .interpreterbase import ObjectHolder from .modules import ModuleReturnValue +from .cmake import CMakeInterpreter import os, shutil, uuid import re, shlex @@ -2037,7 +2038,7 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'}, class Interpreter(InterpreterBase): def __init__(self, build, backend=None, subproject='', subdir='', subproject_dir='subprojects', - modules = None, default_project_options=None, mock=False): + modules = None, default_project_options=None, mock=False, ast=None): super().__init__(build.environment.get_source_dir(), subdir) self.an_unpicklable_object = mesonlib.an_unpicklable_object self.build = build @@ -2054,9 +2055,12 @@ class Interpreter(InterpreterBase): self.subproject_directory_name = subdir.split(os.path.sep)[-1] self.subproject_dir = subproject_dir self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') - if not mock: + if not mock and ast is None: self.load_root_meson_file() self.sanity_check_ast() + elif ast is not None: + self.ast = ast + self.sanity_check_ast() self.builtin.update({'meson': MesonMain(build, self)}) self.generators = [] self.visited_subdirs = {} @@ -2243,7 +2247,7 @@ class Interpreter(InterpreterBase): raise InterpreterException('Stdlib definition for %s should have exactly two elements.' % l) projname, depname = di - subproj = self.do_subproject(projname, {}) + subproj = self.do_subproject(projname, 'meson', {}) self.build.cross_stdlibs[l] = subproj.get_variable_method([depname], {}) except KeyError: pass @@ -2418,13 +2422,13 @@ external dependencies (including libraries) must go to "dependencies".''') if len(args) != 1: raise InterpreterException('Subproject takes exactly one argument') dirname = args[0] - return self.do_subproject(dirname, kwargs) + return self.do_subproject(dirname, 'meson', kwargs) def disabled_subproject(self, dirname): self.subprojects[dirname] = SubprojectHolder(None, self.subproject_dir, dirname) return self.subprojects[dirname] - def do_subproject(self, dirname, kwargs): + def do_subproject(self, dirname: str, method: str, kwargs): disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) if disabled: mlog.log('Subproject', mlog.bold(dirname), ':', 'skipped: feature', mlog.bold(feature), 'disabled') @@ -2457,7 +2461,7 @@ external dependencies (including libraries) must go to "dependencies".''') 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')) try: - resolved = r.resolve(dirname) + resolved = r.resolve(dirname, method) except wrap.WrapException as e: subprojdir = os.path.join(self.subproject_dir, r.directory) if isinstance(e, wrap.WrapNotFoundException): @@ -2473,22 +2477,20 @@ 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) os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True) self.global_args_frozen = True + mlog.log() with mlog.nested(): - mlog.log('Executing subproject', mlog.bold(dirname), '\n') + mlog.log('Executing subproject', mlog.bold(dirname), 'method', mlog.bold(method), '\n') try: - with mlog.nested(): - new_build = self.build.copy() - subi = Interpreter(new_build, self.backend, dirname, subdir, self.subproject_dir, - self.modules, default_options) - subi.subprojects = self.subprojects - - subi.subproject_stack = self.subproject_stack + [dirname] - current_active = self.active_projectname - subi.run() - mlog.log('Subproject', mlog.bold(dirname), 'finished.') + if method == 'meson': + return self._do_subproject_meson(dirname, subdir, default_options, required, kwargs) + elif method == 'cmake': + return self._do_subproject_cmake(dirname, subdir, subdir_abs, default_options, required, kwargs) + else: + raise InterpreterException('The method {} is invalid for the subproject {}'.format(method, dirname)) # Invalid code is always an error except InvalidCode: raise @@ -2502,6 +2504,18 @@ external dependencies (including libraries) must go to "dependencies".''') return self.disabled_subproject(dirname) raise e + def _do_subproject_meson(self, dirname, subdir, default_options, required, kwargs, ast=None, build_def_files=None): + with mlog.nested(): + new_build = self.build.copy() + subi = Interpreter(new_build, self.backend, dirname, subdir, self.subproject_dir, + self.modules, default_options, ast=ast) + subi.subprojects = self.subprojects + + subi.subproject_stack = self.subproject_stack + [dirname] + current_active = self.active_projectname + subi.run() + mlog.log('Subproject', mlog.bold(dirname), 'finished.') + mlog.log() if 'version' in kwargs: @@ -2513,11 +2527,48 @@ external dependencies (including libraries) must go to "dependencies".''') self.subprojects.update(subi.subprojects) self.subprojects[dirname] = SubprojectHolder(subi, self.subproject_dir, dirname) # Duplicates are possible when subproject uses files from project root - self.build_def_files = list(set(self.build_def_files + subi.build_def_files)) + if build_def_files: + self.build_def_files = list(set(self.build_def_files + build_def_files)) + else: + self.build_def_files = list(set(self.build_def_files + subi.build_def_files)) self.build.merge(subi.build) self.build.subprojects[dirname] = subi.project_version return self.subprojects[dirname] + def _do_subproject_cmake(self, dirname, subdir, subdir_abs, default_options, required, kwargs): + with mlog.nested(): + new_build = self.build.copy() + prefix = self.coredata.builtins['prefix'].value + cmake_options = mesonlib.stringlistify(kwargs.get('cmake_options', [])) + cm_int = CMakeInterpreter(new_build, subdir, subdir_abs, prefix, new_build.environment, self.backend) + cm_int.initialise(cmake_options) + cm_int.analyse() + + # Generate a meson ast and execute it with the normal do_subproject_meson + ast = cm_int.pretend_to_be_meson() + + mlog.log() + with mlog.nested(): + mlog.log('Processing generated meson AST') + mlog.log() + + # Debug print the generated meson file + mlog.debug('=== BEGIN meson.build ===') + from .ast import AstIndentationGenerator, AstPrinter + printer = AstPrinter() + ast.accept(AstIndentationGenerator()) + ast.accept(printer) + printer.post_process() + mlog.debug(printer.result) + mlog.debug('=== END meson.build ===') + mlog.debug() + + result = self._do_subproject_meson(dirname, subdir, default_options, required, kwargs, ast, cm_int.bs_files) + result.cm_interpreter = cm_int + + mlog.log() + return result + def get_option_internal(self, optname): for opts in chain( [self.coredata.base_options, compilers.base_options, self.coredata.builtins], @@ -3105,7 +3156,7 @@ external dependencies (including libraries) must go to "dependencies".''') 'default_options': kwargs.get('default_options', []), 'required': kwargs.get('required', True), } - self.do_subproject(dirname, sp_kwargs) + self.do_subproject(dirname, 'meson', sp_kwargs) return self.get_subproject_dep(display_name, dirname, varname, kwargs) @FeatureNewKwargs('executable', '0.42.0', ['implib']) |