qt: add preserve_paths keyword to functions

This allow to generate ui and moc under subdirectories,
as this is allowed with generic generators.
pull/12839/head
Charles Brunet 2 years ago committed by Dylan Baker
parent 6c2c4612cc
commit f4f50db441
  1. 17
      docs/markdown/Qt6-module.md
  2. 15
      docs/markdown/_include_qt_base.md
  3. 10
      docs/markdown/snippets/qt_preserve_path_from.md
  4. 38
      mesonbuild/modules/qt.py
  5. 2
      test cases/frameworks/4 qt/mainWindow.h
  6. 10
      test cases/frameworks/4 qt/meson.build
  7. 0
      test cases/frameworks/4 qt/ui/mainWindow.ui

@ -39,6 +39,11 @@ It takes no positional arguments, and the following keyword arguments:
*New in 0.60.0*: support for custom_target, custom_target_index, and generator_output.
- `extra_args` string[]: Extra arguments to pass directly to `qt-uic`
- `method` string: The method to use to detect Qt, see [[dependency]]
- `preserve_paths` bool: *New in 1.4.0*. If `true`, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called `subdir/one.input` is processed
it generates a file `{target private directory}/subdir/one.out` when `true`,
and `{target private directory}/one.out` when `false` (default).
## compile_moc
@ -59,6 +64,11 @@ It takes no positional arguments, and the following keyword arguments:
- `dependencies`: dependency objects whose include directories are used by moc.
- `include_directories` (string | IncludeDirectory)[]: A list of `include_directory()`
objects used when transpiling the .moc files
- `preserve_paths` bool: *New in 1.4.0*. If `true`, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called `subdir/one.input` is processed
it generates a file `{target private directory}/subdir/one.out` when `true`,
and `{target private directory}/one.out` when `false` (default).
## preprocess
@ -96,7 +106,12 @@ This method takes the following keyword arguments:
- `dependencies` Dependency[]: dependency objects needed by moc.
- *Deprecated in 0.59.0.*: `sources`: a list of extra sources, which are added
to the output unchanged.
- `preserve_paths` bool: *Since 1.4.0*. If `true`, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called `subdir/one.input` is processed
it generates a file `{target private directory}/subdir/one.out` when `true`,
and `{target private directory}/one.out` when `false` (default).
It returns an array of targets and sources to pass to a compilation target.
## compile_translations

@ -28,6 +28,11 @@ It takes no positional arguments, and the following keyword arguments:
- `extra_args` string[]: Extra arguments to pass directly to `qt-uic`
- `method` string: The method to use to detect Qt, see `dependency()` for more
information.
- `preserve_paths` bool: *Since 1.4.0*. If `true`, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called `subdir/one.input` is processed
it generates a file `{target private directory}/subdir/one.out` when `true`,
and `{target private directory}/one.out` when `false` (default).
## compile_moc
@ -49,6 +54,11 @@ It takes no positional arguments, and the following keyword arguments:
- `dependencies`: dependency objects whose include directories are used by moc.
- `include_directories` (string | IncludeDirectory)[]: A list of `include_directory()`
objects used when transpiling the .moc files
- `preserve_paths` bool: *New in 1.4.0*. If `true`, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called `subdir/one.input` is processed
it generates a file `{target private directory}/subdir/one.out` when `true`,
and `{target private directory}/one.out` when `false` (default).
## preprocess
@ -78,6 +88,11 @@ This method takes the following keyword arguments:
- `rcc_extra_arguments` string[]: any additional arguments to `rcc`. Since v0.49.0.
- `dependencies` Dependency[]: dependency objects needed by moc. Available since v0.48.0.
- `sources`: a list of extra sources, which are added to the output unchanged. Deprecated in 0.59.0.
- `preserve_paths` bool: *New in 1.4.0*. If `true`, specifies that the output
files need to maintain their directory structure inside the target temporary
directory. For instance, when a file called `subdir/one.input` is processed
it generates a file `{target private directory}/subdir/one.out` when `true`,
and `{target private directory}/one.out` when `false` (default).
It returns an array of targets and sources to pass to a compilation target.

@ -0,0 +1,10 @@
## Added `preserve_paths` keyword argument to qt module functions.
In `qt4`, `qt5`, and `qt6` modules, `compile_ui`, `compile_moc`, and
`preprocess` functions now have a `preserve_paths` keyword argument.
If `'true`, it specifies that the output files need to maintain their directory
structure inside the target temporary directory. For instance, when a file
called `subdir/one.input` is processed it generates a file
`{target private directory}/subdir/one.out` when `true`,
and `{target private directory}/one.out` when `false` (default).

@ -48,6 +48,7 @@ if T.TYPE_CHECKING:
sources: T.Sequence[T.Union[FileOrString, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]]
extra_args: T.List[str]
method: str
preserve_paths: bool
class MocCompilerKwArgs(TypedDict):
@ -59,6 +60,7 @@ if T.TYPE_CHECKING:
method: str
include_directories: T.List[T.Union[str, build.IncludeDirs]]
dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
preserve_paths: bool
class PreprocessKwArgs(TypedDict):
@ -73,6 +75,7 @@ if T.TYPE_CHECKING:
include_directories: T.List[T.Union[str, build.IncludeDirs]]
dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
method: str
preserve_paths: bool
class HasToolKwArgs(kwargs.ExtractRequired):
@ -376,9 +379,10 @@ class QtBaseModule(ExtensionModule):
required=True,
),
KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
KwargInfo('method', str, default='auto')
KwargInfo('method', str, default='auto'),
KwargInfo('preserve_paths', bool, default=False, since='1.4.0'),
)
def compile_ui(self, state: 'ModuleState', args: T.Tuple, kwargs: 'UICompilerKwArgs') -> ModuleReturnValue:
def compile_ui(self, state: ModuleState, args: T.Tuple, kwargs: UICompilerKwArgs) -> ModuleReturnValue:
"""Compile UI resources into cpp headers."""
if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['sources']):
FeatureNew.single_use('qt.compile_ui: custom_target or generator for "sources" keyword argument',
@ -386,7 +390,7 @@ class QtBaseModule(ExtensionModule):
out = self._compile_ui_impl(state, kwargs)
return ModuleReturnValue(out, [out])
def _compile_ui_impl(self, state: 'ModuleState', kwargs: 'UICompilerKwArgs') -> build.GeneratedList:
def _compile_ui_impl(self, state: ModuleState, kwargs: UICompilerKwArgs) -> build.GeneratedList:
# Avoid the FeatureNew when dispatching from preprocess
self._detect_tools(state, kwargs['method'])
if not self.tools['uic'].found():
@ -394,13 +398,14 @@ class QtBaseModule(ExtensionModule):
"please check your qt{2} installation")
raise MesonException(err_msg.format('UIC', f'uic-qt{self.qt_version}', self.qt_version))
preserve_path_from = os.path.join(state.source_root, state.subdir) if kwargs['preserve_paths'] else None
# TODO: This generator isn't added to the generator list in the Interpreter
gen = build.Generator(
self.tools['uic'],
kwargs['extra_args'] + ['-o', '@OUTPUT@', '@INPUT@'],
['ui_@BASENAME@.h'],
name=f'Qt{self.qt_version} ui')
return gen.process_files(kwargs['sources'], state)
return gen.process_files(kwargs['sources'], state, preserve_path_from)
@FeatureNew('qt.compile_moc', '0.59.0')
@noPosargs
@ -422,8 +427,9 @@ class QtBaseModule(ExtensionModule):
KwargInfo('method', str, default='auto'),
KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]),
KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]),
KwargInfo('preserve_paths', bool, default=False, since='1.4.0'),
)
def compile_moc(self, state: 'ModuleState', args: T.Tuple, kwargs: 'MocCompilerKwArgs') -> ModuleReturnValue:
def compile_moc(self, state: ModuleState, args: T.Tuple, kwargs: MocCompilerKwArgs) -> ModuleReturnValue:
if any(isinstance(s, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for s in kwargs['headers']):
FeatureNew.single_use('qt.compile_moc: custom_target or generator for "headers" keyword argument',
'0.60.0', state.subproject, location=state.current_node)
@ -433,7 +439,7 @@ class QtBaseModule(ExtensionModule):
out = self._compile_moc_impl(state, kwargs)
return ModuleReturnValue(out, [out])
def _compile_moc_impl(self, state: 'ModuleState', kwargs: 'MocCompilerKwArgs') -> T.List[build.GeneratedList]:
def _compile_moc_impl(self, state: ModuleState, kwargs: MocCompilerKwArgs) -> T.List[build.GeneratedList]:
# Avoid the FeatureNew when dispatching from preprocess
self._detect_tools(state, kwargs['method'])
if not self.tools['moc'].found():
@ -458,18 +464,19 @@ class QtBaseModule(ExtensionModule):
DEPFILE_ARGS: T.List[str] = ['--output-dep-file'] if self._moc_supports_depfiles else []
arguments = kwargs['extra_args'] + DEPFILE_ARGS + inc + compile_args + ['@INPUT@', '-o', '@OUTPUT@']
preserve_path_from = os.path.join(state.source_root, state.subdir) if kwargs['preserve_paths'] else None
if kwargs['headers']:
moc_gen = build.Generator(
self.tools['moc'], arguments, ['moc_@BASENAME@.cpp'],
depfile='moc_@BASENAME@.cpp.d',
name=f'Qt{self.qt_version} moc header')
output.append(moc_gen.process_files(kwargs['headers'], state))
output.append(moc_gen.process_files(kwargs['headers'], state, preserve_path_from))
if kwargs['sources']:
moc_gen = build.Generator(
self.tools['moc'], arguments, ['@BASENAME@.moc'],
depfile='@BASENAME@.moc.d',
name=f'Qt{self.qt_version} moc source')
output.append(moc_gen.process_files(kwargs['sources'], state))
output.append(moc_gen.process_files(kwargs['sources'], state, preserve_path_from))
return output
@ -487,8 +494,9 @@ class QtBaseModule(ExtensionModule):
KwargInfo('method', str, default='auto'),
KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]),
KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]),
KwargInfo('preserve_paths', bool, default=False, since='1.4.0'),
)
def preprocess(self, state: 'ModuleState', args: T.List[T.Union[str, File]], kwargs: 'PreprocessKwArgs') -> ModuleReturnValue:
def preprocess(self, state: ModuleState, args: T.List[T.Union[str, File]], kwargs: PreprocessKwArgs) -> ModuleReturnValue:
_sources = args[1:]
if _sources:
FeatureDeprecated.single_use('qt.preprocess positional sources', '0.59', state.subproject, location=state.current_node)
@ -502,7 +510,7 @@ class QtBaseModule(ExtensionModule):
if kwargs['qresources']:
# custom output name set? -> one output file, multiple otherwise
rcc_kwargs: 'ResourceCompilerKwArgs' = {'name': '', 'sources': kwargs['qresources'], 'extra_args': kwargs['rcc_extra_arguments'], 'method': method}
rcc_kwargs: ResourceCompilerKwArgs = {'name': '', 'sources': kwargs['qresources'], 'extra_args': kwargs['rcc_extra_arguments'], 'method': method}
if args:
name = args[0]
if not isinstance(name, str):
@ -511,17 +519,23 @@ class QtBaseModule(ExtensionModule):
sources.extend(self._compile_resources_impl(state, rcc_kwargs))
if kwargs['ui_files']:
ui_kwargs: 'UICompilerKwArgs' = {'sources': kwargs['ui_files'], 'extra_args': kwargs['uic_extra_arguments'], 'method': method}
ui_kwargs: UICompilerKwArgs = {
'sources': kwargs['ui_files'],
'extra_args': kwargs['uic_extra_arguments'],
'method': method,
'preserve_paths': kwargs['preserve_paths'],
}
sources.append(self._compile_ui_impl(state, ui_kwargs))
if kwargs['moc_headers'] or kwargs['moc_sources']:
moc_kwargs: 'MocCompilerKwArgs' = {
moc_kwargs: MocCompilerKwArgs = {
'extra_args': kwargs['moc_extra_arguments'],
'sources': kwargs['moc_sources'],
'headers': kwargs['moc_headers'],
'include_directories': kwargs['include_directories'],
'dependencies': kwargs['dependencies'],
'method': method,
'preserve_paths': kwargs['preserve_paths'],
}
sources.extend(self._compile_moc_impl(state, moc_kwargs))

@ -3,7 +3,7 @@
#include <QObject>
#include <QMainWindow>
#include "ui_mainWindow.h"
#include "ui/ui_mainWindow.h"
class NotificationModel;

@ -61,11 +61,15 @@ foreach qt : ['qt4', 'qt5', 'qt6']
method : get_option('method')
)
# XML files that need to be compiled with the uic tol.
prep += qtmodule.compile_ui(sources : 'mainWindow.ui', method: get_option('method'))
prep += qtmodule.compile_ui(
sources : 'ui/mainWindow.ui',
method: get_option('method'),
preserve_paths: true)
qtmodule.preprocess(
ui_files : 'mainWindow.ui',
method: get_option('method'))
ui_files : 'ui/mainWindow.ui',
method: get_option('method'),
preserve_paths: true)
# Resource file(s) for rcc compiler
extra_cpp_args = []

Loading…
Cancel
Save