aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2021-06-01 14:54:57 -0700
committerDylan Baker <dylan@pnwbakers.com>2021-06-15 12:35:15 -0700
commit2322804a4df9811ba75db01230b5df36efd20aee (patch)
tree8115f092c23fdcf976823db7bdd1fcfc1bc539ce
parentec592a4ecae1db61b9748ec7d2388f738cdb4737 (diff)
downloadmeson-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__.py5
-rw-r--r--mesonbuild/modules/qt.py60
-rw-r--r--test cases/frameworks/4 qt/meson.build8
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',