diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2021-06-01 14:54:57 -0700 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2021-06-15 12:35:15 -0700 |
commit | 2322804a4df9811ba75db01230b5df36efd20aee (patch) | |
tree | 8115f092c23fdcf976823db7bdd1fcfc1bc539ce | |
parent | ec592a4ecae1db61b9748ec7d2388f738cdb4737 (diff) | |
download | meson-2322804a4df9811ba75db01230b5df36efd20aee.zip meson-2322804a4df9811ba75db01230b5df36efd20aee.tar.gz meson-2322804a4df9811ba75db01230b5df36efd20aee.tar.bz2 |
modules/qt: Add a compile_moc method
This method only compiles moc resources, nothing else
-rw-r--r-- | mesonbuild/modules/__init__.py | 5 | ||||
-rw-r--r-- | mesonbuild/modules/qt.py | 60 | ||||
-rw-r--r-- | test cases/frameworks/4 qt/meson.build | 8 |
3 files changed, 66 insertions, 7 deletions
diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index e95b9c6..31890d3 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -23,6 +23,7 @@ import typing as T if T.TYPE_CHECKING: from ..interpreter import Interpreter + from ..interpreter.interpreterobjects import IncludeDirsHolder from ..interpreterbase import TYPE_var, TYPE_nvar, TYPE_nkwargs class ModuleState: @@ -59,14 +60,14 @@ class ModuleState: self.target_machine = interpreter.builtin['target_machine'].held_object self.current_node = interpreter.current_node - def get_include_args(self, include_dirs, prefix='-I'): + def get_include_args(self, include_dirs: T.Iterable[T.Union[str, 'IncludeDirsHolder']], prefix: str = '-I') -> T.List[str]: if not include_dirs: return [] srcdir = self.environment.get_source_dir() builddir = self.environment.get_build_dir() - dirs_str = [] + dirs_str: T.List[str] = [] for dirs in unholder(include_dirs): if isinstance(dirs, str): dirs_str += [f'{prefix}{dirs}'] diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index f3e6f27..439f995 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -27,6 +27,7 @@ from . import ModuleReturnValue, ExtensionModule from ..interpreterbase import ContainerTypeInfo, FeatureDeprecated, FeatureDeprecatedKwargs, KwargInfo, noPosargs, permittedKwargs, FeatureNew, FeatureNewKwargs, typed_kwargs from ..interpreter import extract_required_kwarg from ..programs import NonExistingExternalProgram +from ..interpreter.interpreterobjects import DependencyHolder, ExternalLibraryHolder, IncludeDirsHolder if T.TYPE_CHECKING: from . import ModuleState @@ -54,6 +55,17 @@ if T.TYPE_CHECKING: extra_args: T.List[str] method: str + class MocCompilerKwArgs(TypedDict): + + """Keyword arguments for the Moc Compiler method.""" + + sources: T.Optional[T.List[mesonlib.FileOrString]] + headers: T.Optional[T.List[mesonlib.FileOrString]] + extra_args: T.Optional[T.List[str]] + method: str + include_directories: T.Optional[T.List[IncludeDirsHolder]] + dependencies: T.Optional[T.List[T.Union[DependencyHolder, ExternalLibraryHolder]]] + class QtBaseModule(ExtensionModule): tools_detected = False @@ -72,6 +84,7 @@ class QtBaseModule(ExtensionModule): 'compile_translations': self.compile_translations, 'compile_resources': self.compile_resources, 'compile_ui': self.compile_ui, + 'compile_moc': self.compile_moc, }) def compilers_detect(self, state, qt_dep: 'QtBaseDependency') -> None: @@ -302,12 +315,57 @@ class QtBaseModule(ExtensionModule): out = gen.process_files(f'Qt{self.qt_version} ui', kwargs['sources'], state) return ModuleReturnValue(out, [out]) # type: ignore + @FeatureNew('qt.compile_moc', '0.59.0') + @noPosargs + @typed_kwargs( + 'qt.compile_moc', + KwargInfo('sources', ContainerTypeInfo(list, (File, str)), listify=True), + KwargInfo('headers', ContainerTypeInfo(list, (File, str)), listify=True), + KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True), + KwargInfo('method', str, default='auto'), + KwargInfo('include_directories', ContainerTypeInfo(list, IncludeDirsHolder), listify=True), + KwargInfo('dependencies', ContainerTypeInfo(list, (DependencyHolder, ExternalLibraryHolder)), listify=True), + ) + def compile_moc(self, state: 'ModuleState', args: T.Tuple, kwargs: 'MocCompilerKwArgs') -> ModuleReturnValue: + self._detect_tools(state, kwargs['method']) + if not self.moc.found(): + err_msg = ("{0} sources specified and couldn't find {1}, " + "please check your qt{2} installation") + raise MesonException(err_msg.format('MOC', f'uic-qt{self.qt_version}', self.qt_version)) + + if not (kwargs['headers'] or kwargs['sources']): + raise build.InvalidArguments('At least one of the "headers" or "sources" keyword arguments must be provied and not empty') + + inc = state.get_include_args(include_dirs=kwargs['include_directories'] or []) + compile_args: T.List[str] = [] + if kwargs['dependencies']: + for dep in unholder(kwargs['dependencies']): + compile_args.extend([a for a in dep.get_all_compile_args() if a.startswith(('-I', '-D'))]) + + output: T.List[build.GeneratedList] = [] + + extra_args: T.List[str] = kwargs['extra_args'] or [] + arguments = extra_args + inc + compile_args + ['@INPUT@', '-o', '@OUTPUT@'] + if kwargs['headers']: + moc_kwargs = {'output': 'moc_@BASENAME@.cpp', + 'arguments': arguments} + moc_gen = build.Generator([self.moc], moc_kwargs) + output.append(moc_gen.process_files(f'Qt{self.qt_version} moc header', kwargs['headers'], state)) + if kwargs['sources']: + moc_kwargs = {'output': '@BASENAME@.moc', + 'arguments': arguments} + moc_gen = build.Generator([self.moc], moc_kwargs) + output.append(moc_gen.process_files(f'Qt{self.qt_version} moc source', kwargs['sources'], state)) + + return ModuleReturnValue(output, [output]) + @FeatureNewKwargs('qt.preprocess', '0.49.0', ['uic_extra_arguments']) @FeatureNewKwargs('qt.preprocess', '0.44.0', ['moc_extra_arguments']) @FeatureNewKwargs('qt.preprocess', '0.49.0', ['rcc_extra_arguments']) @FeatureDeprecatedKwargs('qt.preprocess', '0.59.0', ['sources']) @permittedKwargs({'moc_headers', 'moc_sources', 'uic_extra_arguments', 'moc_extra_arguments', 'rcc_extra_arguments', 'include_directories', 'dependencies', 'ui_files', 'qresources', 'method'}) - def preprocess(self, state, args, kwargs): + # We can't use typed_pos_args here, the signature is ambiguious + def preprocess(self, state: 'ModuleState', args: T.List[str], kwargs): rcc_files, ui_files, moc_headers, moc_sources, uic_extra_arguments, moc_extra_arguments, rcc_extra_arguments, sources, include_directories, dependencies \ = [extract_as_list(kwargs, c, pop=True) for c in ['qresources', 'ui_files', 'moc_headers', 'moc_sources', 'uic_extra_arguments', 'moc_extra_arguments', 'rcc_extra_arguments', 'sources', 'include_directories', 'dependencies']] _sources = args[1:] diff --git a/test cases/frameworks/4 qt/meson.build b/test cases/frameworks/4 qt/meson.build index b6f244a..2e85ddb 100644 --- a/test cases/frameworks/4 qt/meson.build +++ b/test cases/frameworks/4 qt/meson.build @@ -100,10 +100,10 @@ foreach qt : ['qt4', 'qt5', 'qt6'] # The build system needs to include the cpp files from # headers but the user must manually include moc # files from sources. - manpreprocessed = qtmodule.preprocess( - moc_extra_arguments : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `moc_extra_arguments` - moc_sources : 'manualinclude.cpp', - moc_headers : 'manualinclude.h', + manpreprocessed = qtmodule.compile_moc( + extra_args : ['-DMOC_EXTRA_FLAG'], # This is just a random macro to test `extra_arguments` + sources : 'manualinclude.cpp', + headers : 'manualinclude.h', method : get_option('method')) qtmaninclude = executable(qt + 'maninclude', |